source: 3thparty/jupload/src/main/java/wjhk/jupload2/policies/DefaultUploadPolicy.java @ 3951

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

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

Line 
1//
2// $Id: DefaultUploadPolicy.java 289 2007-06-19 10:04:46 +0000 (mar., 19 juin
3// 2007) etienne_sf $
4//
5// jupload - A file upload juploadContext.
6// Copyright 2007 The JUpload Team
7//
8// Created: 2006-05-04
9// Creator: etienne_sf
10// Last modified: $Date: 2010-08-18 08:23:24 -0300 (Qua, 18 Ago 2010) $
11//
12// This program is free software; you can redistribute it and/or modify it under
13// the terms of the GNU General Public License as published by the Free Software
14// Foundation; either version 2 of the License, or (at your option) any later
15// version. This program is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18// details. You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software Foundation, Inc.,
20// 675 Mass Ave, Cambridge, MA 02139, USA.
21
22package wjhk.jupload2.policies;
23
24import java.awt.BorderLayout;
25import java.awt.Cursor;
26import java.awt.GridLayout;
27import java.awt.SystemColor;
28import java.awt.dnd.DropTargetDropEvent;
29import java.io.BufferedReader;
30import java.io.ByteArrayOutputStream;
31import java.io.File;
32import java.io.FileOutputStream;
33import java.io.FileReader;
34import java.io.IOException;
35import java.io.InputStream;
36import java.io.PrintStream;
37import java.io.UnsupportedEncodingException;
38import java.net.MalformedURLException;
39import java.net.URL;
40import java.net.URLEncoder;
41import java.nio.charset.Charset;
42import java.nio.charset.UnsupportedCharsetException;
43import java.util.IllegalFormatException;
44import java.util.Iterator;
45import java.util.Locale;
46import java.util.ResourceBundle;
47import java.util.Vector;
48import java.util.regex.Matcher;
49import java.util.regex.Pattern;
50import java.util.regex.PatternSyntaxException;
51
52import javax.swing.BorderFactory;
53import javax.swing.BoxLayout;
54import javax.swing.Icon;
55import javax.swing.JButton;
56import javax.swing.JLabel;
57import javax.swing.JOptionPane;
58import javax.swing.JPanel;
59import javax.swing.JProgressBar;
60import javax.swing.UIManager;
61import javax.swing.UnsupportedLookAndFeelException;
62import javax.swing.border.BevelBorder;
63
64import wjhk.jupload2.context.JUploadContext;
65import wjhk.jupload2.exception.JUploadException;
66import wjhk.jupload2.exception.JUploadExceptionStopAddingFiles;
67import wjhk.jupload2.exception.JUploadExceptionUploadFailed;
68import wjhk.jupload2.exception.JUploadExceptionUploadFailedSuccessNotFound;
69import wjhk.jupload2.exception.JUploadIOException;
70import wjhk.jupload2.filedata.DefaultFileData;
71import wjhk.jupload2.filedata.FileData;
72import wjhk.jupload2.gui.JUploadFileChooser;
73import wjhk.jupload2.gui.JUploadFileFilter;
74import wjhk.jupload2.gui.JUploadPanel;
75import wjhk.jupload2.upload.helper.ByteArrayEncoder;
76import wjhk.jupload2.upload.helper.ByteArrayEncoderHTTP;
77import wjhk.jupload2.upload.helper.HTTPConnectionHelper;
78import wjhk.jupload2.upload.helper.HttpProtocolFinderThread;
79import wjhk.jupload2.upload.helper.InteractiveTrustManager;
80
81/**
82 * This class implements all {@link wjhk.jupload2.policies.UploadPolicy}
83 * methods. Its way of working is he same as the JUpload version 1. <BR>
84 * The simplest way to use this policy is given in the presentation of
85 * {@link UploadPolicy}. The DefaultUploadPolicy is used when no
86 * <I>uploadPolicy</I> parameter is given to the juploadContext, or this
87 * parameter has 'DefaultUploadPolicy' as a value. <BR>
88 * <P>
89 * The <U>default behavior</U> is representated below. It can be overridden by
90 * adding parameters to the juploadContext. All available parameters are shown
91 * in the presentation of {@link UploadPolicy}.
92 * </P>
93 * <UL>
94 * <LI>Default implementation for all
95 * {@link wjhk.jupload2.policies.UploadPolicy} methods.
96 * <LI>Files are uploaded all in one HTTP request.
97 * <LI>No handling for particular kind of files: files are transmitted without
98 * any transformation.
99 * <LI>The file are transmitted to the server with the navigator cookies,
100 * userAgent and Protocol (see also the readCookieFromNavigator and
101 * serverProtocol juploadContext parameter). This make upload occurs within the
102 * current user session on the server. So, it allows right management and
103 * context during the management of uploaded files, on the server.
104 * </UL>
105 *
106 * @author etienne_sf
107 * @version $Revision: 1388 $
108 */
109
110public class DefaultUploadPolicy implements UploadPolicy {
111
112        /**
113         * Maximum number of characters allowed for a message that is displayed in a
114         * DialogBox
115         */
116        public final static int DIALOG_MESSAGE_MAX_LINE_LENGTH = 80;
117
118        // //////////////////////////////////////////////////////////////////////////////////////////////
119        // /////////////////// APPLET PARAMETERS
120        // ///////////////////////////////////////////////////
121        // //////////////////////////////////////////////////////////////////////////////////////////////
122
123        /**
124         * juploadContext contains the reference of the Applet. It's useful to
125         * interact with it. <BR>
126         * It also allows access to the navigator properties, if the html tag
127         * MAYSCRIPT is put in the APPLET tag. This allows this class to get the
128         * cookie, userAgent and protocol, to upload files in the current user
129         * session on the server. <BR>
130         * Default : no default value
131         */
132        JUploadContext juploadContext = null;
133
134        /**
135         * Contains the applet parameter of the same name. If a valid URL is given
136         * here, the navigator will get redirected to this page, after a successful
137         * upload.
138         */
139        private String afterUploadURL = UploadPolicy.DEFAULT_AFTER_UPLOAD_URL;
140
141        /**
142         * Contains the allowedFileExtensions applet parameter.
143         */
144        private boolean allowHttpPersistent = UploadPolicy.DEFAULT_ALLOW_HTTP_PERSISTENT;
145
146        /**
147         * Contains the allowedFileExtensions applet parameter.
148         */
149        private String allowedFileExtensions = UploadPolicy.DEFAULT_ALLOWED_FILE_EXTENSIONS;
150
151        /**
152         * Indicate whether the log window is shown or not to the user. In all cases
153         * it remains in memory, and stores all debug information. This allows a log
154         * information, in case of an error occurs.
155         *
156         * @see #urlToSendErrorTo
157         */
158        private String showLogWindow = UploadPolicy.DEFAULT_SHOW_LOGWINDOW;
159
160        private boolean showStatusbar = UploadPolicy.DEFAULT_SHOW_STATUSBAR;
161
162        private String specificHeaders = null;
163
164        /** Indicates the directory in which the file chooser is to be opened */
165        private File currentBrowsingDirectory = null;
166
167        /**
168         * This parameter controls whether the applet generates a debug file or not.
169         * If true, this file contains the full debug output, whatever the current
170         * debugLevel is.
171         */
172        private boolean debugGenerateFile = true;
173
174        /**
175         * The current debug level. This control the details of information that is
176         * written in the log part of the applet.
177         */
178        private int debugLevel = UploadPolicy.DEFAULT_DEBUG_LEVEL;
179
180        /**
181         * Stored value for the fileChooserIconFromFileContent applet property.
182         *
183         * @see UploadPolicy#PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT
184         */
185        private int fileChooserIconFromFileContent = UploadPolicy.DEFAULT_FILE_CHOOSER_ICON_FROM_FILE_CONTENT;
186
187        /**
188         * Stored value for the fileChooserIconSize applet property.
189         *
190         * @see UploadPolicy#PROP_FILE_CHOOSER_ICON_SIZE
191         */
192        private int fileChooserIconSize = UploadPolicy.DEFAULT_FILE_CHOOSER_ICON_SIZE;
193
194        /**
195         * Stored value for the {@link UploadPolicy#PROP_FILE_FILTER_NAME}
196         */
197        private String fileFilterName = UploadPolicy.DEFAULT_FILE_FILTER_NAME;
198        /**
199         * This String contains the filenameEncoding parameter. All details about
200         * the available applet parameters are displayed in the <a
201         * href="UploadPolicy.html@parameters">Upload Policy javadoc page</a>.
202         */
203        private String filenameEncoding = UploadPolicy.DEFAULT_FILENAME_ENCODING;
204
205        /**
206         * Default value for the ftpCreateDirectoryStructure applet parameter
207         */
208        private boolean ftpCreateDirectoryStructure = UploadPolicy.DEFAULT_FTP_CREATE_DIRECTORY_STRUCTURE;
209
210        /**
211         * Default value for the ftpCreateDirectoryStructure applet parameter
212         */
213        private boolean ftpTransfertBinary = UploadPolicy.DEFAULT_FTP_TRANSFERT_BINARY;
214
215        /**
216         * Default value for the ftpCreateDirectoryStructure applet parameter
217         */
218        private boolean ftpTransfertPassive = UploadPolicy.DEFAULT_FTP_TRANSFERT_PASSIVE;
219
220        /** Default value for the httpUploadParameterName applet parameter */
221        protected String httpUploadParameterName = UploadPolicy.DEFAULT_HTTP_UPLOAD_PARAMETER_NAME;
222
223        /** Default value for the httpUploadParameterType applet parameter */
224        protected String httpUploadParameterType = UploadPolicy.DEFAULT_HTTP_UPLOAD_PARAMETER_TYPE;
225
226        /**
227         * The lang parameter, given to the applet.
228         */
229        private String lang = UploadPolicy.DEFAULT_LANG;
230
231        /**
232         * The current Locale. If the lang parameter is given and value, this
233         * supersede the default locale.
234         */
235        private Locale locale = Locale.getDefault();
236
237        /**
238         * Contains the last exception that occurs in the applet.
239         *
240         * @see #displayErr(String, Exception)
241         */
242        private JUploadException lastException = null;
243
244        /**
245         * The look and feel is used as a parameter of the
246         * UIManager.setLookAndFeel(String) method. See the parameters list on the
247         * {@link UploadPolicy} page.
248         */
249        private String lookAndFeel = UploadPolicy.DEFAULT_LOOK_AND_FEEL;
250
251        /**
252         * The applet will do as may HTTP requests to upload all files, with the
253         * number as a maximum number of files for each HTTP request. <BR>
254         * Default : -1
255         */
256        private int nbFilesPerRequest = UploadPolicy.DEFAULT_NB_FILES_PER_REQUEST;
257
258        /**
259         * Current value (or default value) of the maxChunkSize applet parameter. <BR>
260         * Default : Long.MAX_VALUE
261         */
262        private long maxChunkSize = UploadPolicy.DEFAULT_MAX_CHUNK_SIZE;
263
264        /**
265         * Current value (or default value) of the maxFileSize applet parameter. <BR>
266         * Default : Long.MAX_VALUE
267         */
268        private long maxFileSize = UploadPolicy.DEFAULT_MAX_FILE_SIZE;
269
270        /**
271         * The URL where files should be posted. <BR>
272         * Default : no default value. (mandatory)
273         */
274        private String postURL = UploadPolicy.DEFAULT_POST_URL;
275
276        /** @see UploadPolicy#getReadCookieFromNavigator() */
277        private boolean readCookieFromNavigator = UploadPolicy.DEFAULT_READ_COOKIE_FROM_NAVIGATOR;
278
279        /** @see UploadPolicy#getReadUserAgentFromNavigator() */
280        private boolean readUserAgentFromNavigator = UploadPolicy.DEFAULT_READ_USER_AGENT_FROM_NAVIGATOR;
281
282        /** @see UploadPolicy#getRetryMaxNumberOf() */
283        private int retryMaxNumberOf = UploadPolicy.DEFAULT_RETRY_MAX_NUMBER_OF;
284
285        /** @see UploadPolicy#getRetryNbSecondsBetween() */
286        private int retryNbSecondsBetween = UploadPolicy.DEFAULT_RETRY_NB_SECONDS_BETWEEN;
287
288        /** @see UploadPolicy#getSendMD5Sum() */
289        private boolean sendMD5Sum = UploadPolicy.DEFAULT_SEND_MD5_SUM;
290
291        /** @see UploadPolicy#getServerProtocol() */
292        private String serverProtocol = UploadPolicy.DEFAULT_SERVER_PROTOCOL;
293
294        /**
295         * @see UploadPolicy#getStringUploadError()
296         */
297        private String stringUploadError = UploadPolicy.DEFAULT_STRING_UPLOAD_ERROR;
298
299        /**
300         * @see UploadPolicy#getStringUploadSuccess()
301         */
302        private String stringUploadSuccess = UploadPolicy.DEFAULT_STRING_UPLOAD_SUCCESS;
303
304        /**
305         * @see UploadPolicy#getStringUploadWarning()
306         */
307        private String stringUploadWarning = UploadPolicy.DEFAULT_STRING_UPLOAD_WARNING;
308
309        /**
310         * If an error occurs during upload, and this attribute is not null, the
311         * applet asks the user if wants to send the debug ouput to the
312         * administrator. If yes, the full debug information is POSTed to this URL.
313         * It's a little development on the server side to send a mail to the
314         * webmaster, or just log this error into a log file.
315         *
316         * @see UploadPolicy#sendDebugInformation(String, Exception)
317         */
318        private String urlToSendErrorTo = UploadPolicy.DEFAULT_URL_TO_SEND_ERROR_TO;
319
320        /**
321         * Optional name of a form (in the same document like the applet) which is
322         * used to populate POST parameters.
323         */
324        private String formData = UploadPolicy.DEFAULT_FORMDATA;
325
326        private String afterUploadTarget = UploadPolicy.DEFAULT_AFTER_UPLOAD_TARGET;
327
328        private String lastResponseBody = null;
329
330        protected String lastResponseMessage = null;
331
332        private int sslVerifyCert = InteractiveTrustManager.NONE;
333
334        private final String CRLF = System.getProperty("line.separator");
335
336        // //////////////////////////////////////////////////////////////////////////////////////////////
337        // /////////////////// INTERNAL ATTRIBUTE
338        // ///////////////////////////////////////////////////
339        // //////////////////////////////////////////////////////////////////////////////////////////////
340
341        /**
342         * This Vector contains headers that will be added for each upload. It may
343         * contains specific cookies, for instance.
344         *
345         * @see #onAppendHeader(ByteArrayEncoder)
346         */
347        private Vector<String> headers = new Vector<String>();
348
349        /**
350         * The resourceBundle contains all localized String (and others ??)
351         */
352        private ResourceBundle resourceBundle = null;
353
354        /**
355         * This stream is used to store all information that could be useful, in
356         * case a problem occurs. Is content can then be sent to the webmaster.
357         */
358        protected PrintStream debugOut = null;
359
360        /**
361         * The actual file, used for the debug log.
362         *
363         * @see #debugGenerateFile
364         */
365        protected File debugFile = null;
366
367        /**
368         * This flag prevents endless repeats of opening the debug log, if that
369         * failed for some reason.
370         */
371        protected boolean debugOk = true;
372
373        /**
374         * Same as {@link #patternSuccess}, but for the error message. If found,
375         * then the upload was accepted by the remote HTTP server, but rejected by
376         * the remote application. This pattern should also find the error message
377         * in the first matching string.
378         */
379        protected Pattern patternError = Pattern
380                        .compile(UploadPolicy.DEFAULT_STRING_UPLOAD_ERROR);
381
382        /**
383         * The regexp pattern that is used to find the success string in the HTTP
384         * response. If found, the upload is considered to be a success: it has been
385         * accepted by the remote server and the remote application.
386         */
387        protected Pattern patternSuccess = Pattern
388                        .compile(UploadPolicy.DEFAULT_STRING_UPLOAD_SUCCESS);
389
390        /**
391         * Same as {@link #patternSuccess}, but for the warning message. Each time
392         * it is found, a message is displayed to the user.
393         */
394        protected Pattern patternWarning = Pattern
395                        .compile(UploadPolicy.DEFAULT_STRING_UPLOAD_WARNING);
396
397        // //////////////////////////////////////////////////////////////////////////////////////////////
398        // /////////////////// CONSTRUCTORS
399        // //////////////////////////////////////////////////////////////////////////////////////////////
400
401        /**
402         * The main constructor : use default values, and the given postURL.
403         *
404         * @param juploadContext
405         *            The current juploadContext. As the reference to the current
406         *            upload policy exists almost everywhere, this parameter allows
407         *            any access to anyone on the juploadContext... including
408         *            reading the applet parameters.
409         * @throws JUploadException
410         *             If an applet parameter is invalid
411         */
412        public DefaultUploadPolicy(JUploadContext juploadContext)
413                        throws JUploadException {
414                // Call default constructor for all default initialization;.
415                this.juploadContext = juploadContext;
416                displayInfo("JUpload juploadContext started, with "
417                                + this.getClass().getName() + " upload policy");
418
419                // get the debug level. This control the level of debug messages that
420                // are written in the log window (see displayDebugMessage). In all
421                // cases, the full output is written in the debugBufferString (see also
422                // urlToSendErrorTo)
423                setDebugLevel(juploadContext.getParameter(PROP_DEBUG_LEVEL,
424                                DEFAULT_DEBUG_LEVEL), false);
425
426                // Get resource file. This must be the very first parameter to be set,
427                // because during initialization, translations may be needed.
428                setLang(juploadContext.getParameter(PROP_LANG, DEFAULT_LANG));
429
430                // Force the look and feel of the current system. This must be the
431                // second
432                // first parameter to be set, because during initialization, dialogs can
433                // appear.
434                setLookAndFeel(juploadContext.getParameter(PROP_LOOK_AND_FEEL,
435                                DEFAULT_LOOK_AND_FEEL));
436
437                // This must be set before any URL's because these might trigger an
438                // connection attempt.
439                setSslVerifyCert(juploadContext.getParameter(PROP_SSL_VERIFY_CERT,
440                                DEFAULT_SSL_VERIFY_CERT));
441
442                // get the afterUploadURL juploadContext parameter.
443                setAfterUploadURL(juploadContext.getParameter(PROP_AFTER_UPLOAD_URL,
444                                DEFAULT_AFTER_UPLOAD_URL));
445
446                // FTP: whether or not to create subfolders on the server side.
447                setFtpCreateDirectoryStructure(juploadContext.getParameter(
448                                PROP_FTP_CREATE_DIRECTORY_STRUCTURE,
449                                DEFAULT_FTP_CREATE_DIRECTORY_STRUCTURE));
450                // FTP transfert mode
451                setFtpTransfertBinary(juploadContext.getParameter(
452                                PROP_FTP_TRANSFERT_BINARY, DEFAULT_FTP_TRANSFERT_BINARY));
453                // FTP connection mode
454                setFtpTransfertPassive(juploadContext.getParameter(
455                                PROP_FTP_TRANSFERT_PASSIVE, DEFAULT_FTP_TRANSFERT_PASSIVE));
456
457                // get the fileChooser parameters
458                setAllowedFileExtensions(juploadContext.getParameter(
459                                PROP_ALLOWED_FILE_EXTENSIONS, DEFAULT_ALLOWED_FILE_EXTENSIONS));
460                setFileFilterName(juploadContext.getParameter(PROP_FILE_FILTER_NAME,
461                                DEFAULT_FILE_FILTER_NAME));
462
463                setAllowHttpPersistent(juploadContext.getParameter(
464                                PROP_ALLOW_HTTP_PERSISTENT, DEFAULT_ALLOW_HTTP_PERSISTENT));
465
466                setShowStatusbar(juploadContext.getParameter(PROP_SHOW_STATUSBAR,
467                                DEFAULT_SHOW_STATUSBAR));
468
469                setShowLogWindow(juploadContext.getParameter(PROP_SHOW_LOGWINDOW,
470                                DEFAULT_SHOW_LOGWINDOW));
471
472                // set the fileChooser relative stuff.
473                setFileChooserIconFromFileContent(juploadContext.getParameter(
474                                PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT,
475                                DEFAULT_FILE_CHOOSER_ICON_FROM_FILE_CONTENT));
476                setFileChooserIconSize(juploadContext.getParameter(
477                                PROP_FILE_CHOOSER_ICON_SIZE, DEFAULT_FILE_CHOOSER_ICON_SIZE));
478                setCurrentBrowsingDirectory(juploadContext.getParameter(
479                                PROP_BROWSING_DIRECTORY, DEFAULT_BROWSING_DIRECTORY));
480                // get the filenameEncoding. If not null, it should be a valid argument
481                // for the URLEncoder.encode method.
482                // DEPRECATED.
483                setFilenameEncoding(juploadContext.getParameter(PROP_FILENAME_ENCODING,
484                                DEFAULT_FILENAME_ENCODING));
485
486                // Read parameters about the HTTP upload request.
487                setNbFilesPerRequest(juploadContext.getParameter(
488                                PROP_NB_FILES_PER_REQUEST, DEFAULT_NB_FILES_PER_REQUEST));
489                setHttpUploadParameterName(juploadContext.getParameter(
490                                PROP_HTTP_UPLOAD_PARAMETER_NAME,
491                                DEFAULT_HTTP_UPLOAD_PARAMETER_NAME));
492                setHttpUploadParameterType(juploadContext.getParameter(
493                                PROP_HTTP_UPLOAD_PARAMETER_TYPE,
494                                DEFAULT_HTTP_UPLOAD_PARAMETER_TYPE));
495                // get the maximum size of a file on one HTTP request (indicates if the
496                // file must be splitted before upload, see UploadPolicy comment).
497                setMaxChunkSize(juploadContext.getParameter(PROP_MAX_CHUNK_SIZE,
498                                DEFAULT_MAX_CHUNK_SIZE));
499                // get the maximum size of an uploaded file.
500                setMaxFileSize(juploadContext.getParameter(PROP_MAX_FILE_SIZE,
501                                DEFAULT_MAX_FILE_SIZE));
502                // retry management
503                setRetryMaxNumberOf(juploadContext.getParameter(
504                                PROP_RETRY_MAX_NUMBER_OF, DEFAULT_RETRY_MAX_NUMBER_OF));
505                setRetryNbSecondsBetween(juploadContext
506                                .getParameter(PROP_RETRY_NB_SECONDS_BETWEEN,
507                                                DEFAULT_RETRY_NB_SECONDS_BETWEEN));
508
509                // get the URL where files must be posted.
510                setPostURL(juploadContext.getParameter(PROP_POST_URL, DEFAULT_POST_URL));
511
512                // get any additional headers.
513                setReadCookieFromNavigator(juploadContext.getParameter(
514                                PROP_READ_COOKIE_FROM_NAVIGATOR,
515                                DEFAULT_READ_COOKIE_FROM_NAVIGATOR));
516                setReadUserAgentFromNavigator(juploadContext.getParameter(
517                                PROP_READ_USER_AGENT_FROM_NAVIGATOR,
518                                DEFAULT_READ_USER_AGENT_FROM_NAVIGATOR));
519                setSendMD5Sum(juploadContext.getParameter(PROP_SEND_MD5_SUM,
520                                DEFAULT_SEND_MD5_SUM));
521                setSpecificHeaders(juploadContext.getParameter(PROP_SPECIFIC_HEADERS,
522                                DEFAULT_SPECIFIC_HEADERS));
523                setStringUploadError(juploadContext.getParameter(
524                                PROP_STRING_UPLOAD_ERROR, DEFAULT_STRING_UPLOAD_ERROR));
525                setStringUploadSuccess(juploadContext.getParameter(
526                                PROP_STRING_UPLOAD_SUCCESS, DEFAULT_STRING_UPLOAD_SUCCESS));
527                setStringUploadWarning(juploadContext.getParameter(
528                                PROP_STRING_UPLOAD_WARNING, DEFAULT_STRING_UPLOAD_WARNING));
529
530                // get the URL where the full debug output can be sent when an error
531                // occurs.
532                setUrlToSendErrorTo(juploadContext.getParameter(
533                                PROP_URL_TO_SEND_ERROR_TO, DEFAULT_URL_TO_SEND_ERROR_TO));
534                this.formData = juploadContext.getParameter(PROP_FORMDATA,
535                                DEFAULT_FORMDATA);
536                this.afterUploadTarget = juploadContext.getParameter(
537                                PROP_AFTER_UPLOAD_TARGET, DEFAULT_AFTER_UPLOAD_TARGET);
538
539                // Let's touch the server, to test that everything is Ok. Take care,
540                // this is the only place where we override the default value, by null:
541                // the default value will be used by the HttpConnect.getProtocol()
542                // method.
543                // Also, in FTP mode, there can be no default value.
544                HttpProtocolFinderThread.computeServerProtocol(this, juploadContext
545                                .getParameter(PROP_SERVER_PROTOCOL, null));
546
547                // We let the UploadPolicyFactory call the displayParameterStatus
548                // method, so that the initialization is finished, including for classes
549                // which inherit from DefaultUploadPolicy.
550                displayDebug(
551                                "[DefaultUploadPolicy] end of constructor (serverProtocol has been set)",
552                                30);
553        }
554
555        // //////////////////////////////////////////////////////////////////////////////////////////////
556        // /////////////////// UploadPolicy methods
557        // //////////////////////////////////////////////////////////////////////////////////////////////
558
559        /** @see UploadPolicy#start() */
560        public void start() {
561                // The current context may add any specific headers.
562                if (getReadCookieFromNavigator()) {
563                        this.juploadContext.readCookieFromNavigator(this.headers);
564                }
565                if (getReadUserAgentFromNavigator()) {
566                        this.juploadContext.readUserAgentFromNavigator(this.headers);
567                }
568        }
569       
570       
571        // getters and setters are sorted below
572
573        /**
574         * @see wjhk.jupload2.policies.UploadPolicy#addHeader(java.lang.String)
575         */
576        public void addHeader(String header) {
577                this.headers.add(header);
578        }
579
580        /**
581         * The default behavior (see {@link DefaultUploadPolicy}) is to check that
582         * the stringUploadSuccess applet parameter is present in the response from
583         * the server. The return is tested, in the order below: <DIR> <LI>False, if
584         * the stringUploadError is found. An error message is then displayed. <LI>
585         * True, if the stringUploadSuccess is null or empty (no test at all). <LI>
586         * True, if the stringUploadSuccess string is present in the
587         * serverOutputBody. <LI>True, If previous condition is not filled, but the
588         * HTTP header "HTTP(.*)200OK$" is present: the test is currently non
589         * blocking, because I can not test all possible HTTP configurations.<BR>
590         * <LI>False if the previous conditions are not fullfilled. </DIR> <BR>
591         * This method also looks for the stringUploadWarning regular expression.
592         * Each time it is matched, the found message is displayed to the user.
593         *
594         * @param status
595         *            The HTTP response code
596         * @param msg
597         *            The status message from the first line of the response (e.g.
598         *            "200 OK").
599         * @param body
600         *            The body of the HTTP answer.
601         * @return True or False, indicating if the upload is a success or not.
602         * @see UploadPolicy#checkUploadSuccess(int, String, String)
603         */
604        public boolean checkUploadSuccess(int status, String msg, String body)
605                        throws JUploadException {
606                boolean bReturn = false;
607
608                if (getDebugLevel() > 100) {
609                        // Let's have a little time to check the upload messages written on
610                        // the progress bar.
611                        try {
612                                Thread.sleep(300);
613                        } catch (InterruptedException e) {
614                        }
615                }
616
617                this.lastResponseBody = body;
618                this.lastResponseMessage = msg;
619                displayDebug("HTTP status: " + msg, 30);
620                // HTTP-100 correction, thanks to Marc Reidy
621                if ((status != 200) && (status != 100))
622                        throw new JUploadExceptionUploadFailed("Received HTTP status "
623                                        + msg);
624
625                // HTTP-100 "continue", in case we're uploading
626                // to an ASP.NET development server. We should
627                // continue sending...
628                if(status == 100)
629                    return true;
630
631                // Let's analyze the body returned, line by line. The end of line
632                // character may be CR, LF, or CRLF. We navigate through the body, and
633                // replace any end of line character by a uniform CRLF.
634                Matcher matcherError, matcherWarning;
635                String line;
636                Pattern p = Pattern.compile("[\\r\\n]", Pattern.MULTILINE);
637                String[] lines = p.split(body);
638                StringBuffer sbBodyWithUniformCRLF = new StringBuffer(body.length());
639                for (int i = 0; i < lines.length; i += 1) {
640                        line = lines[i];
641                        sbBodyWithUniformCRLF.append(line).append("\r\n");
642
643                        // FIXME some empty lines are given by the server
644                        // Let's remove the empty line: with the p pattern, a multiline is
645                        // generated each time a \r\n is received, that is: for each line.
646                        if (line == null || line.equals("")) {
647                                // An empty line. Let's go the next line.
648                                continue;
649                        }
650
651                        // Check if this is a success
652                        // The success string should be in the http body
653                        if (getStringUploadSuccess() != null
654                                        && !getStringUploadSuccess().equals("")) {
655                                if (this.patternSuccess.matcher(line).matches()) {
656                                        // We go on. There may be some WARNING message, hereafter.
657                                        bReturn = true;
658                                }
659                        }
660
661                        // Check if this is an error
662                        if (getStringUploadError() != null
663                                        && !getStringUploadError().equals("")) {
664                                matcherError = this.patternError.matcher(line);
665                                if (matcherError.matches()) {
666                                        String errmsg = "An error occurs during upload (but the applet couldn't find the error message)";
667                                        if (matcherError.groupCount() > 0) {
668                                                if (!matcherError.group(1).equals("")) {
669                                                        // Let's do a (very simple) formatting: one line to
670                                                        // 100 characters
671                                                        errmsg = formatMessage(matcherError.group(1));
672                                                }
673                                        }
674                                        this.lastResponseMessage = errmsg;
675                                        throw new JUploadExceptionUploadFailed(errmsg);
676                                }
677                        }// getStringUploadError
678
679                        // Check if this is an warning
680                        if (getStringUploadWarning() != null
681                                        && !getStringUploadWarning().equals("")) {
682                                matcherWarning = this.patternWarning.matcher(line);
683                                if (matcherWarning.matches()) {
684                                        String warnmsg = "A warning occurs during upload (but the applet couldn't find the warning message)";
685                                        if (matcherWarning.groupCount() > 0) {
686                                                if (!matcherWarning.group(1).equals("")) {
687                                                        warnmsg = formatMessage(matcherWarning.group(1));
688                                                }
689                                        }
690                                        this.lastResponseMessage = warnmsg;
691                                        displayWarn(warnmsg);
692                                        alertStr(warnmsg);
693                                }
694                        }// getStringUploadWarning
695
696                }// while(st.hasMoreTokens())
697
698                if (bReturn) {
699                        return true;
700                }
701
702                // We found no stringUploadSuccess nor stringUploadError
703                if (getStringUploadSuccess() == null
704                                || getStringUploadSuccess().equals("")) {
705                        // No chance to check the correctness of this upload. -> Assume Ok
706                        return true;
707                }
708
709                // stringUploadSuccess was defined but we did not find it.
710                // This is most certainly an error as http-status 200 does *not* refer
711                // to the correctness of the content. It merely means that the protocol
712                // handling was ok. -> throw an exception
713                throw new JUploadExceptionUploadFailedSuccessNotFound(getClass()
714                                .getName()
715                                + ".checkUploadSuccess(): The regexp string \""
716                                + getStringUploadSuccess()
717                                + "\" was not found in the response body");
718        } // checkUploadSuccess
719
720        /**
721         * Generation of a formatted error message, so that it can be displayed in a
722         * DialogBox. That is: each line that contains more than
723         * {@link #DIALOG_MESSAGE_MAX_LINE_LENGTH} is truncated to
724         * DIALOG_MESSAGE_MAX_LINE_LENGTH.
725         *
726         * @param msg
727         * @return
728         */
729        protected String formatMessage(String msg) {
730                StringBuffer sbMsg = new StringBuffer();
731                String[] lines = msg.split("\\\\n");
732                for (int i = 0; i < lines.length; i += 1) {
733                        // For each line, we truncate it, if it's too long.
734                        String line = lines[i];
735                        for (int j = 0, remaining = line.length(); remaining > 0; remaining -= DIALOG_MESSAGE_MAX_LINE_LENGTH, j += 1) {
736                                if (remaining <= DIALOG_MESSAGE_MAX_LINE_LENGTH) {
737                                        // It's the last loop.
738                                        sbMsg.append(line.substring(j
739                                                        * DIALOG_MESSAGE_MAX_LINE_LENGTH));
740                                } else {
741                                        sbMsg.append(line.substring(j
742                                                        * DIALOG_MESSAGE_MAX_LINE_LENGTH, (j + 1)
743                                                        * DIALOG_MESSAGE_MAX_LINE_LENGTH));
744                                        sbMsg.append("\n");
745                                }
746                        }
747                        // End we add the EOL characters, for all lines, but the last one.
748                        if (i < lines.length - 1) {
749                                sbMsg.append("\n");
750                        }
751                }
752
753                return sbMsg.toString();
754        }
755
756        /**
757         * @see wjhk.jupload2.policies.UploadPolicy#afterUpload(Exception, String)
758         */
759        public void afterUpload(Exception e, String serverOutput)
760                        throws JUploadException {
761                // If there was no error, and afterUploadURL is defined, let's try to go
762                // to this URL.
763                String url = getAfterUploadURL();
764                if (url != null) {
765                        this.juploadContext.displayURL(url, e == null);
766                }
767        }
768
769        /** @see UploadPolicy#alertStr(String) */
770        public void alertStr(String str) {
771                String str2 = str.replaceAll("\\\\n", "\n");
772                JOptionPane.showMessageDialog(null, str2, "Alert",
773                                JOptionPane.WARNING_MESSAGE);
774        }
775
776        /** @see UploadPolicy#confirmDialogStr(String, int) */
777        public int confirmDialogStr(String str, int optionTypes) {
778                String str2 = str.replaceAll("\\\\n", "\n");
779                return JOptionPane.showConfirmDialog(getContext().getUploadPanel()
780                                .getJComponent().getParent(), str2, "Alert", optionTypes);
781        }
782
783        /** @see UploadPolicy#alert(String) */
784        public void alert(String key) {
785                alertStr(getLocalizedString(key));
786        }
787
788        /**
789         * The DefaultUpload accepts all file types: we just return an instance of
790         * FileData, without any test.
791         *
792         * @exception JUploadExceptionStopAddingFiles
793         *                If the users choosed to stop adding. This occurs when the
794         *                {@link #fileFilterAccept(File)} method returns false, and
795         *                the user then choose to stop adding files.
796         * @see UploadPolicy#createFileData(File, File)
797         */
798        public FileData createFileData(File file, File root)
799                        throws JUploadExceptionStopAddingFiles {
800                if (!fileFilterAccept(file)) {
801                        String msg = file.getName() + " : "
802                                        + getLocalizedString("errForbiddenExtension");
803                        displayWarn(msg);
804                        if (confirmDialogStr(msg, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
805                                // The user want to stop to add files to the list. For instance,
806                                // when he/she added a whole directory, and it contains a lot of
807                                // files that don't match the allowed file extension.
808                                throw new JUploadExceptionStopAddingFiles("Stopped by the user");
809                        }
810                        return null;
811                } else if (!file.canRead()) {
812                        displayInfo("Can't read file " + file.getName()
813                                        + ". No DefaultFileData creation.");
814                        return null;
815                } else {
816                        return new DefaultFileData(file, root, this);
817                }
818        }
819
820        /**
821         * Default implementation of
822         * {@link wjhk.jupload2.policies.UploadPolicy#createTopPanel(JButton, JButton, JButton, JUploadPanel)}
823         * . IT creates a JPanel, containing the three given JButton. It creates the
824         * same panel as the original JUpload.
825         *
826         * @see wjhk.jupload2.policies.UploadPolicy#createTopPanel(JButton, JButton,
827         *      JButton, JUploadPanel)
828         */
829        public JPanel createTopPanel(JButton browse, JButton remove,
830                        JButton removeAll, JUploadPanel jUploadPanel) {
831                JPanel jPanel = new JPanel();
832
833                jPanel.setLayout(new GridLayout(1, 3, 10, 5));
834                jPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
835                jPanel.add(browse);
836                jPanel.add(removeAll);
837                jPanel.add(remove);
838
839                jUploadPanel.getJComponent().setBorder(
840                                BorderFactory.createLineBorder(SystemColor.controlDkShadow));
841
842                return jPanel;
843        }
844
845        /**
846         * @see wjhk.jupload2.policies.UploadPolicy#createProgressPanel(JProgressBar,
847         *      JProgressBar, JButton, JButton, JUploadPanel)
848         */
849        public JPanel createProgressPanel(JProgressBar preparationProgressBar,
850                        JProgressBar uploadProgressBar, JButton uploadButton,
851                        JButton stopButton, JUploadPanel mainPanel) {
852
853                // There may be two progress bar: one for preparation progress of files
854                // (preparation before upload) and one to follow the actual upload.
855                JPanel jProgressBarPanel = new JPanel();
856                jProgressBarPanel.setLayout(new BorderLayout(10, 1));
857                jProgressBarPanel.add(preparationProgressBar, BorderLayout.NORTH);
858                jProgressBarPanel.add(uploadProgressBar, BorderLayout.SOUTH);
859
860                JPanel jProgressPanel = new JPanel();
861                jProgressPanel.setLayout(new BorderLayout(10, 0));
862                jProgressPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
863                jProgressPanel.add(uploadButton, BorderLayout.LINE_START);
864                jProgressPanel.add(jProgressBarPanel, BorderLayout.CENTER);
865                jProgressPanel.add(stopButton, BorderLayout.LINE_END);
866                return jProgressPanel;
867        }
868
869        /**
870         * @see wjhk.jupload2.policies.UploadPolicy#createStatusBar(javax.swing.JLabel,
871         *      JUploadPanel)
872         */
873        public JPanel createStatusBar(JLabel content, JUploadPanel mainPanel) {
874                if (this.showStatusbar) {
875                        JPanel pstatus = new JPanel();
876                        pstatus.setLayout(new BorderLayout());
877                        pstatus.add(content, BorderLayout.CENTER);
878                        pstatus.setBorder(new BevelBorder(BevelBorder.LOWERED));
879                        return pstatus;
880                }
881                return null;
882        }
883
884        /**
885         * This methods allow the upload policy to override the default disposition
886         * of the components on the applet.
887         *
888         * @see UploadPolicy#addComponentsToJUploadPanel(JUploadPanel)
889         */
890        public void addComponentsToJUploadPanel(JUploadPanel jUploadPanel) {
891                // Set the global layout of the panel.
892                jUploadPanel.getJComponent().setLayout(
893                                new BoxLayout(jUploadPanel.getJComponent(), BoxLayout.Y_AXIS));
894
895                // The top panel is the upper part of the applet: above the file
896                // list.
897                // JPanel topPanel = new JPanel();
898                JPanel topPanel = createTopPanel(jUploadPanel.getBrowseButton(),
899                                jUploadPanel.getRemoveButton(), jUploadPanel
900                                                .getRemoveAllButton(), jUploadPanel);
901                if (topPanel != null) {
902                        jUploadPanel.getJComponent().add(topPanel);
903                        topPanel.addMouseListener(jUploadPanel.getMouseListener());
904                }
905
906                // Then, we add the file list.
907                jUploadPanel.getJComponent().add(
908                                jUploadPanel.getFilePanel().getDropComponent());
909
910                // The progress panel contains the progress bar, and the upload and stop
911                // buttons.
912                JPanel progressPanel = createProgressPanel(jUploadPanel
913                                .getPreparationProgressBar(), jUploadPanel
914                                .getUploadProgressBar(), jUploadPanel.getUploadButton(),
915                                jUploadPanel.getStopButton(), jUploadPanel);
916                jUploadPanel.getJComponent().add(progressPanel);
917                jUploadPanel.getJComponent().addMouseListener(
918                                jUploadPanel.getMouseListener());
919
920                // Now, we add the log window.
921                jUploadPanel.showOrHideLogWindow();
922                jUploadPanel.getJComponent().add(jUploadPanel.getJLogWindowPane());
923
924                // And, to finish with: the status bar.
925                JPanel p = createStatusBar(jUploadPanel.getStatusLabel(), jUploadPanel);
926                if (null != p) {
927                        jUploadPanel.getJComponent().add(p);
928                        p.addMouseListener(jUploadPanel.getMouseListener());
929                }
930        }
931
932        /** {@inheritDoc} */
933        public void updateButtonState(int executionStatus) {
934                // First step: check the parameter.
935                if (executionStatus != UploadPolicy.EXEC_STATUS_READY
936                                && executionStatus != UploadPolicy.EXEC_STATUS_UPLOADING) {
937                        throw new java.lang.IllegalArgumentException(
938                                        "Unknow value for executionStatus: " + executionStatus);
939                }
940
941                // Then ... nothing to do! This class has no specific GUI item.
942        }
943
944        /** @see UploadPolicy#displayErr(Exception) */
945        public void displayErr(Exception e) {
946                displayErr(e.getMessage(), e);
947        }
948
949        /** @see UploadPolicy#displayErr(String) */
950        public void displayErr(String err) {
951                displayErr(err, null);
952        }
953
954        /**
955         * Logs a stack trace for the given exception.
956         *
957         * @param throwable
958         */
959        private void displayStackTrace(Throwable throwable) {
960                if (throwable != null) {
961                        ByteArrayOutputStream bs = new ByteArrayOutputStream();
962                        PrintStream ps = new PrintStream(bs);
963                        throwable.printStackTrace(ps);
964                        ps.close();
965                        displayMsg("", bs.toString());
966
967                        // If there is a cause, let's be sure its stack trace is displayed.
968                        if (throwable.getCause() != null) {
969                                displayMsg("", "Caused by:");
970                                displayStackTrace(throwable.getCause());
971                        }
972                }
973        }
974
975        /**
976         * This method just logs an error.
977         *
978         * @param errorText
979         * @param exception
980         */
981        private void logErr(String errorText, Exception exception) {
982                if (exception == null) {
983                        setLastException(new JUploadException("errorText"));
984                } else if (exception instanceof JUploadException) {
985                        setLastException((JUploadException) exception);
986                } else {
987                        setLastException(new JUploadException(exception));
988                }
989
990                // Default behavior: if debugLevel is 0, and an error occurs, we force
991                // the debug level to 1: this makes the log window become visible, if it
992                // was hidden.
993                if (getDebugLevel() == 0)
994                        setDebugLevel(1);
995
996                String exceptionMsg = null;
997                String exceptionClassName = null;
998                String logMsg = errorText;
999
1000                // First, we construct the exception class name.
1001                if (exception == null) {
1002                        exceptionClassName = "";
1003                } else if (exception instanceof JUploadException) {
1004                        exceptionClassName = "["
1005                                        + ((JUploadException) exception).getClassNameAndClause()
1006                                        + "] ";
1007                } else {
1008                        exceptionClassName = "[" + exception.getClass().getName() + "] ";
1009                }
1010
1011                // Then, the message body can be completed by the exception message.
1012                if (exception != null) {
1013                        // Ok, we have an exception.
1014                        if (exception.getCause() != null) {
1015                                exceptionMsg = exception.getCause().getMessage();
1016                        } else {
1017                                exceptionMsg = exception.getMessage();
1018                        }
1019                        logMsg = exceptionMsg + " (" + errorText + ")";
1020                }
1021
1022                // Add the message to the log window
1023                displayMsg("[ERROR]", exceptionClassName + logMsg);
1024                // Let's display the stack trace, if relevant.
1025                displayStackTrace(exception);
1026
1027                // Then we copy the debug output to the clipboard, and say it to the
1028                // current user.
1029                if (this.juploadContext.getUploadPanel() != null
1030                                && getDebugLevel() >= 99) {
1031                        // Ok, the applet has been fully built.
1032                        this.juploadContext.getUploadPanel().copyLogWindow();
1033                        alert("messageLogWindowCopiedToClipboard");
1034                }
1035
1036        }
1037
1038        /**
1039         * If debug is off, the log window may not be visible. We switch the debug
1040         * to on, to be sure that some information will be displayed to the user. <BR>
1041         * If debug is -1, the log window remains hidden.
1042         *
1043         * @see wjhk.jupload2.policies.UploadPolicy#displayErr(java.lang.String,
1044         *      java.lang.Exception, int)
1045         */
1046        public int displayErr(String errorText, Exception exception, int optionTypes) {
1047                // Then, we display it to the user.
1048                String alertMsg = errorText;
1049                // Then, the message body can be completed by the exception message.
1050                if (exception != null && (errorText == null || errorText.equals(""))) {
1051                        // Ok, we have an exception.
1052                        if (exception.getCause() != null) {
1053                                alertMsg = exception.getCause().getMessage();
1054                        } else {
1055                                alertMsg = exception.getMessage();
1056                        }
1057                }
1058
1059                // The message displayed depend on the debug level:
1060                if (getDebugLevel() >= 30 && exception != null) {
1061                        alertMsg = exception.getClass().getName() + ": " + alertMsg;
1062                }
1063
1064                // Display the message to the user. The kind of alert box depends on the
1065                // given options:
1066                int buttonClicked = 0;
1067                switch (optionTypes) {
1068                case -1:
1069                        // Standard message box.
1070                        alertStr(alertMsg);
1071                        buttonClicked = JOptionPane.OK_OPTION;
1072                        break;
1073                case JOptionPane.OK_CANCEL_OPTION:
1074                case JOptionPane.YES_NO_CANCEL_OPTION:
1075                case JOptionPane.YES_NO_OPTION:
1076                        buttonClicked = confirmDialogStr(alertMsg, optionTypes);
1077                        break;
1078                default:
1079                        // This is a problem. Let's display it to the user as a standard
1080                        // alert box.
1081                        alertStr(alertMsg);
1082                        buttonClicked = JOptionPane.OK_OPTION;
1083                        // Then, we log this new problem.
1084                        String msg = "Unknown optionType in displayErr(String, Exception, int)";
1085                        alertStr(msg);
1086                        logErr(msg, null);
1087                }
1088
1089                // First, we log the error.
1090                logErr(errorText, exception);
1091
1092                return buttonClicked;
1093        }
1094
1095        /**
1096         * If debug is off, the log window may not be visible. We switch the debug
1097         * to on, to be sure that some information will be displayed to the user. <BR>
1098         * If debug is -1, the log window remains hidden.
1099         *
1100         * @see wjhk.jupload2.policies.UploadPolicy#displayErr(java.lang.String,
1101         *      java.lang.Exception)
1102         */
1103        public void displayErr(String errorText, Exception exception) {
1104                displayErr(errorText, exception, -1);
1105        }
1106
1107        /**
1108         * @see UploadPolicy#displayInfo(String)
1109         */
1110        public void displayInfo(String info) {
1111                displayMsg("[INFO]", info);
1112        }
1113
1114        /**
1115         * @see UploadPolicy#displayWarn(String)
1116         */
1117        public void displayWarn(String warn) {
1118                displayMsg("[WARN]", warn);
1119        }
1120
1121        /**
1122         * @see UploadPolicy#displayDebug(String, int)
1123         */
1124        public void displayDebug(String debug, int minDebugLevel) {
1125                final String tag = "[DEBUG]";
1126                if (this.debugLevel >= minDebugLevel) {
1127                        // displayMsg will add the message to the debugStrignBuffer.
1128                        displayMsg(tag, debug);
1129                } else if (this.debugGenerateFile) {
1130                        // We have to write the message to the debug file, whatever the
1131                        // debugLevel is.
1132                        addMsgToDebugLog(tag + debug);
1133                }
1134        }
1135
1136        /** @see UploadPolicy#getLocalizedString(String, Object...) */
1137        public String getLocalizedString(String key, Object... args) {
1138                String ret = this.resourceBundle.getString(key);
1139                try {
1140                        // We have to recreate the correct call to String.format
1141                        switch (args.length) {
1142                        case 0:
1143                                return String.format(ret);
1144                        case 1:
1145                                return String.format(ret, args[0]);
1146                        case 2:
1147                                return String.format(ret, args[0], args[1]);
1148                        case 3:
1149                                return String.format(ret, args[0], args[1], args[2]);
1150                        case 4:
1151                                return String.format(ret, args[0], args[1], args[2], args[3]);
1152                        case 5:
1153                                return String.format(ret, args[0], args[1], args[2], args[3],
1154                                                args[4]);
1155                        case 6:
1156                                return String.format(ret, args[0], args[1], args[2], args[3],
1157                                                args[4], args[5]);
1158                        case 7:
1159                                return String.format(ret, args[0], args[1], args[2], args[3],
1160                                                args[4], args[5], args[6]);
1161                        default:
1162                                throw new IllegalArgumentException(
1163                                                "DefaultUploadPolicy.getLocalizedString accepts up to 7 variable parameters ("
1164                                                                + args.length
1165                                                                + " values were given for the 'args' argument");
1166                        }
1167                } catch (IllegalFormatException ife) {
1168                        displayErr(ife.getClass().getName() + " (" + ife.getMessage()
1169                                        + ")when managing this string: " + ret);
1170                        throw ife;
1171                }
1172        }
1173
1174        /**
1175         * @see UploadPolicy#getUploadFilename(FileData, int)
1176         */
1177        public String getUploadFilename(FileData fileData, int index)
1178                        throws JUploadException {
1179                return getEncodedFilename(fileData.getFileName());
1180        }
1181
1182        /**
1183         * returns the filename and encodes it, if necessary
1184         *
1185         * @param filename
1186         *            the original filename
1187         * @return filename (encoded, if necessary)
1188         * @throws JUploadException
1189         */
1190        protected final String getEncodedFilename(String filename)
1191                        throws JUploadException {
1192                if (this.filenameEncoding == null || this.filenameEncoding.equals("")) {
1193                        return filename;
1194                }
1195                try {
1196                        return URLEncoder.encode(filename, this.filenameEncoding);
1197                } catch (UnsupportedEncodingException e) {
1198                        throw new JUploadException(e);
1199                }
1200        }
1201
1202        /** @see UploadPolicy#getUploadName(FileData, int) */
1203        public String getUploadName(FileData fileData, int index)
1204                        throws JUploadException {
1205                if (this.httpUploadParameterType
1206                                .equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ARRAY)) {
1207                        return this.httpUploadParameterName + "[]";
1208                } else if (this.httpUploadParameterType
1209                                .equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ITERATION)) {
1210                        return this.httpUploadParameterName + index;
1211                } else if (this.httpUploadParameterType
1212                                .equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)) {
1213                        // Only valid if nbFilesPerRequest is 1. Let's check it.
1214                        if (getNbFilesPerRequest() == 1) {
1215                                return this.httpUploadParameterName;
1216                        } else {
1217                                throw new JUploadException(
1218                                                UploadPolicy.PROP_HTTP_UPLOAD_PARAMETER_TYPE
1219                                                                + " value '" + this.httpUploadParameterType
1220                                                                + "' is only valid when '"
1221                                                                + UploadPolicy.PROP_NB_FILES_PER_REQUEST
1222                                                                + " is 1.");
1223                        }
1224                } else {
1225                        throw new JUploadException(
1226                                        UploadPolicy.PROP_HTTP_UPLOAD_PARAMETER_TYPE + " '"
1227                                                        + this.httpUploadParameterType
1228                                                        + "' is not implemented.");
1229                }
1230        }
1231
1232        /** @see UploadPolicy#getHttpUploadParameterName() */
1233        public String getHttpUploadParameterName() {
1234                return this.httpUploadParameterName;
1235        }
1236
1237        /**
1238         * Setter for the {@link #httpUploadParameterName}. This value is used by
1239         * the {@link #getUploadName(FileData, int)} method, to generate the name of
1240         * the upload parameter that will contain the uploaded file.<BR>
1241         * The name must begin by a letter, then contain letter or numbers
1242         *
1243         * @throws JUploadException
1244         *             When the given value is invalid (null, empty string, or
1245         *             contains other characters than letters and/or numbers)
1246         */
1247        protected void setHttpUploadParameterName(String httpUploadParameterName)
1248                        throws JUploadException {
1249                // Some useful checks.
1250                if (httpUploadParameterName == null
1251                                || httpUploadParameterName.equals("")) {
1252                        throw new JUploadException(
1253                                        "httpUploadParameterName may not be null");
1254                }
1255                // Control the parameter name content.
1256                if (!httpUploadParameterName.matches("^[a-zA-Z0-9][a-zA-Z0-9_]*$")) {
1257                        throw new JUploadException(
1258                                        "httpUploadParameterName may only contain letters (lowercase or uppercase) and numbers.");
1259                }
1260
1261                // Ok, we're happy with the given value. Let's store it.
1262                this.httpUploadParameterName = httpUploadParameterName;
1263        }
1264
1265        /** @see UploadPolicy#getHttpUploadParameterType() */
1266        public String getHttpUploadParameterType() {
1267                return this.httpUploadParameterType;
1268        }
1269
1270        /**
1271         * Setter for the {@link #httpUploadParameterType}. This value is used by
1272         * the {@link #getUploadName(FileData, int)} method, to generate the name of
1273         * the upload parameter that will contain the uploaded file. Depending on
1274         * this value, the parameter will be an iteration or an array.
1275         *
1276         * @throws JUploadException
1277         */
1278        protected void setHttpUploadParameterType(String httpUploadParameterType)
1279                        throws JUploadException {
1280                // Some useful checks.
1281                if (httpUploadParameterType == null) {
1282                        throw new JUploadException(
1283                                        "httpUploadParameterType may not be null");
1284                }
1285
1286                // Check against the list of allowed values
1287                if (!httpUploadParameterType
1288                                .equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ARRAY)
1289                                && !httpUploadParameterType
1290                                                .equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ITERATION)
1291                                && !httpUploadParameterType
1292                                                .equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)) {
1293                        throw new JUploadException("'" + httpUploadParameterType
1294                                        + "' is not an allowed value for httpUploadParameterType.");
1295                }
1296
1297                // OneFile is only valid ... when we upload file per file !
1298                if (httpUploadParameterType
1299                                .equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)) {
1300                        if (getNbFilesPerRequest() != 1) {
1301                                throw new JUploadException("'" + httpUploadParameterType
1302                                                + "' is only valid when nbFilesPerRequest is 1.");
1303                        }
1304                }
1305
1306                // Ok, we're happy. Let's store the value !
1307                this.httpUploadParameterType = httpUploadParameterType;
1308        }
1309
1310        /** @see wjhk.jupload2.policies.UploadPolicy#beforeUpload() */
1311        public boolean beforeUpload() {
1312                // Default : nothing to do before upload, so we're ready.
1313                return true;
1314        }
1315
1316        /** @see UploadPolicy#onAppendHeader(ByteArrayEncoder) */
1317        public ByteArrayEncoder onAppendHeader(ByteArrayEncoder bae)
1318                        throws JUploadIOException {
1319                Iterator<String> it = this.headers.iterator();
1320                String header;
1321                displayDebug("[onAppendHeader] Start", 80);
1322                while (it.hasNext()) {
1323                        header = it.next();
1324                        if (header == null || header.equals("")) {
1325                                displayWarn("[onAppendHeader] Found one empty header. Ignoring it.");
1326                        } else {
1327                                bae.append(header).append("\r\n");
1328                                displayDebug("[onAppendHeader] Header appended; " + header, 80);
1329                        }
1330                }
1331                displayDebug("[onAppendHeader] End", 80);
1332                return bae;
1333        }// appendHeader
1334
1335        /**
1336         * Default implementation of the
1337         * {@link wjhk.jupload2.policies.UploadPolicy#onFileSelected(wjhk.jupload2.filedata.FileData)}
1338         * . Nothing's done.
1339         */
1340        public void onFileSelected(FileData fileData) {
1341                // Default implementation : no action
1342        }
1343
1344        /**
1345         * Default implementation of the
1346         * {@link wjhk.jupload2.policies.UploadPolicy#onFileDoubleClicked(FileData)}
1347         * . Nothing's done.
1348         */
1349        public void onFileDoubleClicked(FileData fileData) {
1350                // Default implementation : no action
1351        }
1352
1353        /** @see UploadPolicy#sendDebugInformation(String, Exception) */
1354        public void sendDebugInformation(String description, Exception exception) {
1355                try {
1356                        if (null == getUrlToSendErrorTo()) {
1357                                displayInfo("getUrlToSendErrorTo is null. No debug information is sent.");
1358                                if (exception == null) {
1359                                        displayInfo("  No exception was stored!");
1360                                } else {
1361                                        displayInfo("  The exception was: "
1362                                                        + exception.getClass().getName()
1363                                                        + exception.getMessage());
1364                                }
1365                        } else {
1366                                displayInfo("Sending debug information to "
1367                                                + getUrlToSendErrorTo());
1368                                if (JOptionPane
1369                                                .showConfirmDialog(null,
1370                                                                getLocalizedString("questionSendMailOnError"),
1371                                                                getLocalizedString("Confirm"),
1372                                                                JOptionPane.YES_NO_OPTION,
1373                                                                JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
1374                                        displayDebug(
1375                                                        "[sendDebugInformation] Within response == true",
1376                                                        30);
1377
1378                                        String action = null;
1379                                        String line;
1380                                        HTTPConnectionHelper connectionHelper = null;
1381                                        boolean localDebugOk = this.debugOk;
1382
1383                                        try {
1384                                                URL url = new URL(this.urlToSendErrorTo);
1385                                                connectionHelper = new HTTPConnectionHelper(this);
1386                                                connectionHelper.initRequest(url, "POST", false, true);
1387
1388                                                ByteArrayEncoder baeContent = new ByteArrayEncoderHTTP(
1389                                                                this, connectionHelper.getByteArrayEncoder()
1390                                                                                .getBoundary(), connectionHelper
1391                                                                                .getByteArrayEncoder().getEncoding());
1392                                                // The message is written in English, as it is not sure
1393                                                // that
1394                                                // the webmaster speaks the same language as the current
1395                                                // user.
1396                                                baeContent.appendTextProperty("description",
1397                                                                "An error occured during upload, in JUpload.",
1398                                                                -1);
1399                                                String exceptionClass = null;
1400                                                String exceptionCause = null;
1401                                                String exceptionStackTrace = null;
1402                                                if (exception != null) {
1403                                                        exceptionClass = exception.getClass().getName();
1404                                                        if (exception.getCause() != null) {
1405                                                                exceptionCause = exception.getCause()
1406                                                                                .getClass().getName();
1407                                                        }
1408                                                        StackTraceElement[] elements = exception
1409                                                                        .getStackTrace();
1410                                                        ByteArrayEncoderHTTP baeStackTrace = new ByteArrayEncoderHTTP(
1411                                                                        this, connectionHelper
1412                                                                                        .getByteArrayEncoder()
1413                                                                                        .getBoundary(), connectionHelper
1414                                                                                        .getByteArrayEncoder()
1415                                                                                        .getEncoding());
1416                                                        for (int i = 0; i < elements.length; i += 1) {
1417                                                                baeStackTrace.append(" at ");
1418                                                                baeStackTrace
1419                                                                                .append(elements[i].getClassName());
1420                                                                baeStackTrace.append(".");
1421                                                                baeStackTrace.append(elements[i]
1422                                                                                .getMethodName());
1423                                                                baeStackTrace.append("() [line ");
1424                                                                baeStackTrace.append(Integer
1425                                                                                .toString(elements[i].getLineNumber()));
1426                                                                baeStackTrace.append("]\r\n");
1427                                                        }
1428                                                        baeStackTrace.close();
1429                                                        exceptionStackTrace = baeStackTrace.getString();
1430                                                }
1431                                                baeContent.appendTextProperty("exceptionClass",
1432                                                                exceptionClass, -1);
1433                                                baeContent.appendTextProperty("exceptionCause",
1434                                                                exceptionCause, -1);
1435                                                baeContent.appendTextProperty("exceptionStackTrace",
1436                                                                exceptionStackTrace, -1);
1437
1438                                                String baeBound = connectionHelper
1439                                                                .getByteArrayEncoder().getBoundary();
1440                                                String baeEncoding = connectionHelper
1441                                                                .getByteArrayEncoder().getEncoding();
1442                                                ByteArrayEncoder baeDebug = new ByteArrayEncoderHTTP(
1443                                                                this, baeBound, baeEncoding);
1444                                                if (this.debugGenerateFile) {
1445                                                        // During debug output, we need to make sure that
1446                                                        // the debug log is not changed, so we set debugOk
1447                                                        // to false temporarily. -> Everything goes to
1448                                                        // stdout.
1449                                                        action = "flush (debugGenerateFile=true)";
1450                                                        synchronized (this) {
1451                                                                this.debugOut.flush();
1452                                                                this.debugOk = false;
1453                                                                // First, calculate the size of the strings we
1454                                                                // will
1455                                                                // send.
1456                                                                action = "read debug file (debugGenerateFile=true)";
1457                                                                BufferedReader debugIn = new BufferedReader(
1458                                                                                new FileReader(this.debugFile));
1459                                                                while ((line = debugIn.readLine()) != null) {
1460                                                                        baeDebug.append(line).append("\r\n");
1461                                                                }
1462                                                                debugIn.close();
1463
1464                                                                // We are done with the debug log, so re-enable
1465                                                                // it.
1466                                                                this.debugOk = localDebugOk;
1467                                                        }// synchronized(this)
1468                                                }// if (this.debugGenerateFile)
1469                                                else {
1470                                                        action = "read debug file (debugGenerateFile=false)";
1471                                                        baeDebug.append(this.juploadContext.getLogWindow()
1472                                                                        .getText());
1473                                                }
1474                                                action = "baeDebug.close()";
1475                                                baeDebug.close();
1476
1477                                                baeContent.appendTextProperty("debugOutput", baeDebug
1478                                                                .getString(), -1);
1479                                                baeContent.appendEndPropertyList();
1480                                                // The content has been built.
1481                                                baeContent.close();
1482
1483                                                // byteArrayEncoder
1484                                                // .append("Content-type:
1485                                                // application/x-www-form-urlencoded\r\n");
1486                                                action = "send request";
1487                                                connectionHelper.append(
1488                                                                "Content-Type: multipart/form-data; boundary=")
1489                                                                .append(
1490                                                                                connectionHelper.getBoundary()
1491                                                                                                .substring(2)).append("\r\n");
1492                                                connectionHelper.append("Content-length: ").append(
1493                                                                String.valueOf(baeContent.getEncodedLength()))
1494                                                                .append("\r\n");
1495
1496                                                // Let's send the headers (without baeDescription) ...
1497                                                connectionHelper.sendRequest();
1498                                                // Blank line (end of header)
1499                                                connectionHelper.append("\r\n");
1500                                                connectionHelper.append(baeContent);
1501
1502                                                action = "connectionHelper.readHttpResponse()";
1503                                                int status = connectionHelper.readHttpResponse();
1504
1505                                                displayDebug(
1506                                                                "========================================================================================",
1507                                                                90);
1508                                                displayDebug(
1509                                                                "==================      sendDebugInformation [start]   =================================",
1510                                                                90);
1511                                                displayDebug(
1512                                                                "========================================================================================",
1513                                                                90);
1514                                                displayDebug(
1515                                                                "[sendDebugInformation] Sent to server: \r\n"
1516                                                                                + connectionHelper
1517                                                                                                .getByteArrayEncoder()
1518                                                                                                .getString(), 90);
1519                                                displayDebug(
1520                                                                "========================================================================================",
1521                                                                90);
1522                                                displayDebug(
1523                                                                "[sendDebugInformation] Body received: \r\n"
1524                                                                                + connectionHelper.getResponseBody(),
1525                                                                90);
1526                                                displayDebug(
1527                                                                "========================================================================================",
1528                                                                90);
1529                                                displayDebug(
1530                                                                "==================      sendDebugInformation [end]     =================================",
1531                                                                90);
1532                                                displayDebug(
1533                                                                "========================================================================================",
1534                                                                90);
1535
1536                                                // Is our upload a success ?
1537                                                if (!checkUploadSuccess(status, connectionHelper
1538                                                                .getResponseMsg(), connectionHelper
1539                                                                .getResponseBody())) {
1540                                                        throw new JUploadExceptionUploadFailed(
1541                                                                        getLocalizedString("errHttpResponse"));
1542                                                }
1543
1544                                                displayInfo("debug information sent correctly");
1545                                        } catch (MalformedURLException e) {
1546                                                throw new JUploadIOException(
1547                                                                "Malformed URL Exception for "
1548                                                                                + this.urlToSendErrorTo, e);
1549                                        } catch (Exception e) {
1550                                                this.debugOk = localDebugOk;
1551                                                displayErr(getLocalizedString("errDuringLogManagement")
1552                                                                + " (" + action + ")", e);
1553                                        } finally {
1554                                                this.debugOk = localDebugOk;
1555                                        }
1556                                }
1557                        }
1558                } catch (JUploadIOException e) {
1559                        displayErr("Could not send debug information", e);
1560                }
1561        }// sendDebugInformation
1562
1563        /**
1564         * This method manages all applet parameters. It allows javascript to update
1565         * their value, for instance after the user chooses a value in a list ...
1566         *
1567         * @throws JUploadException
1568         * @see wjhk.jupload2.policies.UploadPolicy#setProperty(java.lang.String,
1569         *      java.lang.String)
1570         */
1571        public void setProperty(String prop, String value) throws JUploadException {
1572
1573                displayDebug("[DefaultUploadPolicy] Call of setProperty: " + prop
1574                                + " => " + value, 30);
1575
1576                if (prop.equals(PROP_AFTER_UPLOAD_URL)) {
1577                        setAfterUploadURL(value);
1578                } else if (prop.equals(PROP_ALLOW_HTTP_PERSISTENT)) {
1579                        setAllowHttpPersistent(Boolean.parseBoolean(value));
1580                } else if (prop.equals(PROP_ALLOWED_FILE_EXTENSIONS)) {
1581                        setAllowedFileExtensions(value);
1582                } else if (prop.equals(PROP_DEBUG_LEVEL)) {
1583                        setDebugLevel(this.juploadContext.parseInt(value, this.debugLevel));
1584                } else if (prop.equals(PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT)) {
1585                        setFileChooserIconFromFileContent(this.juploadContext.parseInt(
1586                                        value, getFileChooserIconFromFileContent()));
1587                } else if (prop.equals(PROP_FILE_CHOOSER_ICON_SIZE)) {
1588                        setFileChooserIconSize(this.juploadContext.parseInt(value,
1589                                        getFileChooserIconSize()));
1590                } else if (prop.equals(PROP_FILE_FILTER_NAME)) {
1591                        setFileFilterName(value);
1592                } else if (prop.equals(PROP_FILENAME_ENCODING)) {
1593                        setFilenameEncoding(value);
1594                } else if (prop.equals(PROP_LANG)) {
1595                        setLang(value);
1596                } else if (prop.equals(PROP_LOOK_AND_FEEL)) {
1597                        setLookAndFeel(value);
1598                } else if (prop.equals(PROP_MAX_CHUNK_SIZE)) {
1599                        setMaxChunkSize(this.juploadContext.parseLong(value,
1600                                        this.maxChunkSize));
1601                } else if (prop.equals(PROP_MAX_FILE_SIZE)) {
1602                        setMaxFileSize(this.juploadContext.parseLong(value,
1603                                        this.maxFileSize));
1604                } else if (prop.equals(PROP_NB_FILES_PER_REQUEST)) {
1605                        setNbFilesPerRequest(this.juploadContext.parseInt(value,
1606                                        this.nbFilesPerRequest));
1607                } else if (prop.equals(PROP_POST_URL)) {
1608                        setPostURL(value);
1609                } else if (prop.equals(PROP_SERVER_PROTOCOL)) {
1610                        HttpProtocolFinderThread.computeServerProtocol(this, value);
1611                } else if (prop.equals(PROP_STRING_UPLOAD_SUCCESS)) {
1612                        setStringUploadSuccess(value);
1613                } else if (prop.equals(PROP_SSL_VERIFY_CERT)) {
1614                        setSslVerifyCert(value);
1615                } else if (prop.equals(PROP_URL_TO_SEND_ERROR_TO)) {
1616                        setUrlToSendErrorTo(value);
1617                } else {
1618                        displayWarn("Unknown applet parameter: " + prop
1619                                        + " (in DefaultUploadPolicy.setProperty)");
1620                }
1621        }
1622
1623        /**
1624         * This method displays the applet parameter list, according to the current
1625         * debugLevel. It is called by the {@link #setDebugLevel(int)} method. It
1626         * should be override by any subclasses, that should display its own
1627         * parameters, then call <I>super.displayParameterStatus()</I>.
1628         *
1629         * @see UploadPolicy#displayParameterStatus()
1630         */
1631        public void displayParameterStatus() {
1632                displayDebug(
1633                                "=======================================================================",
1634                                30);
1635                displayDebug("======= Parameters managed by DefaultUploadPolicy", 30);
1636                // /////////////////////////////////////////////////////////////////////////////
1637                // Let's display some information to the user, about the received
1638                // parameters.
1639                displayInfo("JUpload applet, version "
1640                                + this.juploadContext.getDetailedVersionMessage()
1641                                + " (compiled: " + this.juploadContext.getBuildDate()
1642                                + "), available at http://jupload.sourceforge.net/");
1643                displayDebug("Java version: " + System.getProperty("java.version"), 30);
1644
1645                displayDebug("List of all applet parameters:", 30);
1646                displayDebug("  language: "
1647                                + this.resourceBundle.getLocale().getLanguage(), 30);
1648                displayDebug("  country: "
1649                                + this.resourceBundle.getLocale().getCountry(), 30);
1650
1651                displayDebug(PROP_AFTER_UPLOAD_URL + ": " + getAfterUploadURL(), 30);
1652                displayDebug(PROP_ALLOW_HTTP_PERSISTENT + ": "
1653                                + getAllowHttpPersistent(), 30);
1654                displayDebug(PROP_ALLOWED_FILE_EXTENSIONS + ": "
1655                                + getAllowedFileExtensions(), 30);
1656                displayDebug(PROP_BROWSING_DIRECTORY + " (current value): "
1657                                + getCurrentBrowsingDirectory(), 30);
1658                displayDebug(PROP_DEBUG_LEVEL + ": " + this.debugLevel, 1);
1659                synchronized (this) {
1660                        if (this.debugGenerateFile) {
1661                                displayDebug("  (debugfile: "
1662                                                + this.debugFile.getAbsolutePath() + ")", 1);
1663                        }
1664                }
1665                displayDebug(PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT + ": "
1666                                + getFileChooserIconFromFileContent(), 30);
1667                displayDebug(PROP_FILE_CHOOSER_ICON_SIZE + ": "
1668                                + getFileChooserIconSize(), 30);
1669                displayDebug(PROP_FILE_FILTER_NAME + ": " + getFileFilterName(), 30);
1670                displayDebug(PROP_FILENAME_ENCODING + ": " + getFilenameEncoding(), 30);
1671                displayDebug(PROP_FORMDATA + ": " + getFormdata(), 30);
1672                displayDebug(PROP_FTP_CREATE_DIRECTORY_STRUCTURE + ": "
1673                                + getFtpCreateDirectoryStructure(), 30);
1674                displayDebug(
1675                                PROP_FTP_TRANSFERT_BINARY + ": " + getFtpTransfertBinary(), 30);
1676                displayDebug(PROP_FTP_TRANSFERT_PASSIVE + ": "
1677                                + getFtpTransfertPassive(), 30);
1678                displayDebug(PROP_HTTP_UPLOAD_PARAMETER_NAME + ": "
1679                                + getHttpUploadParameterName(), 30);
1680                displayDebug(PROP_HTTP_UPLOAD_PARAMETER_TYPE + ": "
1681                                + getHttpUploadParameterType(), 30);
1682                displayDebug("lang: " + this.lang, 30);
1683                displayDebug(PROP_MAX_CHUNK_SIZE + ": " + getMaxChunkSize(), 30);
1684                if (this.maxFileSize == Long.MAX_VALUE) {
1685                        // If the maxFileSize was not given, we display its value only
1686                        // in debug mode.
1687                        displayDebug(PROP_MAX_FILE_SIZE + ": " + getMaxFileSize(), 30);
1688                } else {
1689                        // If the maxFileSize was given, we always inform the user.
1690                        displayInfo(PROP_MAX_FILE_SIZE + ": " + getMaxFileSize());
1691                }
1692                displayDebug(PROP_NB_FILES_PER_REQUEST + ": " + getNbFilesPerRequest(),
1693                                30);
1694                displayDebug(PROP_POST_URL + ": " + this.postURL, 30);
1695                displayDebug(PROP_READ_COOKIE_FROM_NAVIGATOR + ": "
1696                                + this.readCookieFromNavigator, 30);
1697                displayDebug(PROP_READ_USER_AGENT_FROM_NAVIGATOR + ": "
1698                                + this.readUserAgentFromNavigator, 30);
1699                displayDebug(PROP_RETRY_MAX_NUMBER_OF + ": " + this.retryMaxNumberOf,
1700                                30);
1701                displayDebug(PROP_RETRY_NB_SECONDS_BETWEEN + ": "
1702                                + this.retryNbSecondsBetween, 30);
1703                displayDebug(PROP_SEND_MD5_SUM + ": " + getSendMD5Sum(), 30);
1704                displayDebug(PROP_SERVER_PROTOCOL + ": " + getServerProtocol(), 30);
1705                displayDebug(PROP_SHOW_LOGWINDOW + ": " + getShowLogWindow(), 30);
1706                displayDebug(PROP_SHOW_STATUSBAR + ": " + this.showStatusbar, 30);
1707                displayDebug(PROP_SPECIFIC_HEADERS + ": " + getSpecificHeaders(), 30);
1708
1709                displayDebug("Headers that will be added to the POST request: ", 30);
1710                for (Iterator<String> it = this.headers.iterator(); it.hasNext();) {
1711                        displayDebug(it.next() + "\n", 30);
1712                }
1713                displayDebug(PROP_STRING_UPLOAD_ERROR + ": " + getStringUploadError(),
1714                                30);
1715                displayDebug(PROP_STRING_UPLOAD_SUCCESS + ": "
1716                                + getStringUploadSuccess(), 30);
1717                displayDebug(PROP_STRING_UPLOAD_WARNING + ": "
1718                                + getStringUploadWarning(), 30);
1719                displayDebug(PROP_URL_TO_SEND_ERROR_TO + ": " + getUrlToSendErrorTo(),
1720                                30);
1721                displayDebug("", 30);
1722        }
1723
1724        // //////////////////////////////////////////////////////////////////////////////////////////////
1725        // /////////////////// getters / setters
1726        // ///////////////////////////////////////////////////
1727        // //////////////////////////////////////////////////////////////////////////////////////////////
1728
1729        /** @see UploadPolicy#getAfterUploadURL() */
1730        public String getAfterUploadURL() {
1731                return this.afterUploadURL;
1732        }
1733
1734        /**
1735         * Set the {@link #afterUploadURL}
1736         *
1737         * @param afterUploadURL
1738         *            The URL to use.
1739         * @throws JUploadException
1740         */
1741        protected void setAfterUploadURL(String afterUploadURL)
1742                        throws JUploadException {
1743                if (null == afterUploadURL)
1744                        return;
1745                if (afterUploadURL.toLowerCase().startsWith("javascript:")) {
1746                        this.afterUploadURL = afterUploadURL;
1747                } else
1748                        this.afterUploadURL = this.juploadContext
1749                                        .normalizeURL(afterUploadURL);
1750        }
1751
1752        /**
1753         * @see wjhk.jupload2.policies.UploadPolicy#getAllowHttpPersistent()
1754         */
1755        public boolean getAllowHttpPersistent() {
1756                return this.allowHttpPersistent;
1757        }
1758
1759        /** @see UploadPolicy#getAllowedFileExtensions() */
1760        public String getAllowedFileExtensions() {
1761                return this.allowedFileExtensions;
1762        }
1763
1764        /**
1765         * @param allowedFileExtensions
1766         *            the allowedFileExtensions to set
1767         */
1768        protected void setAllowedFileExtensions(String allowedFileExtensions) {
1769                if (allowedFileExtensions == null || allowedFileExtensions.equals("")) {
1770                        this.allowedFileExtensions = null;
1771                } else {
1772                        this.allowedFileExtensions = (allowedFileExtensions.startsWith("/") ? ""
1773                                        : "/")
1774                                        + allowedFileExtensions.toLowerCase()
1775                                        + (allowedFileExtensions.endsWith("/") ? "" : "/");
1776                }
1777        }
1778
1779        protected void setAllowHttpPersistent(boolean value) {
1780                this.allowHttpPersistent = value;
1781        }
1782
1783        /** @see UploadPolicy#getContext() */
1784        public JUploadContext getContext() {
1785                return this.juploadContext;
1786        }
1787
1788        /** {@inheritDoc} */
1789        public void setCurrentBrowsingDirectory(File currentBrowsingDirectoryParam) {
1790                try {
1791                        if (currentBrowsingDirectoryParam.isDirectory()) {
1792                                this.currentBrowsingDirectory = currentBrowsingDirectoryParam;
1793                        } else {
1794                                displayWarn("DefaultUploadPolicy.setCurrentBrowsingDirectory(): "
1795                                                + currentBrowsingDirectoryParam + " doesn't exist.");
1796                        }
1797                } catch (SecurityException se) {
1798                        displayWarn(se.getClass().getName()
1799                                        + " in DefaultUploadPolicy.setCurrentBrowsingDirectory(): "
1800                                        + currentBrowsingDirectoryParam + " is ignored.");
1801                }
1802        }
1803
1804        /**
1805         * @param currentBrowsingDirectoryParam
1806         *            The name of the directory that should be the current one.
1807         * @see UploadPolicy#setCurrentBrowsingDirectory(String)
1808         */
1809        public void setCurrentBrowsingDirectory(String currentBrowsingDirectoryParam) {
1810                try {
1811                        if (currentBrowsingDirectoryParam == null) {
1812                                this.currentBrowsingDirectory = null;
1813                        } else {
1814                                // Apparently, Java deosn't manage path beginning by ~. folder
1815                                // is actually ... ~!
1816                                // Let's manager this.
1817                                if (currentBrowsingDirectoryParam.startsWith("~")) {
1818                                        // Let's keep the part of this path that is after the ~
1819                                        currentBrowsingDirectoryParam = System
1820                                                        .getProperty("user.home")
1821                                                        + currentBrowsingDirectoryParam.substring(1);
1822                                }
1823
1824                                this.currentBrowsingDirectory = new File(
1825                                                currentBrowsingDirectoryParam);
1826
1827                                // Let's check that we have a folder.
1828                                if (this.currentBrowsingDirectory != null
1829                                                && !this.currentBrowsingDirectory.isDirectory()) {
1830                                        displayWarn("DefaultUploadPolicy.setCurrentBrowsingDirectory(): <"
1831                                                        + currentBrowsingDirectoryParam
1832                                                        + "> doesn't exist or is not a directory.");
1833                                        this.currentBrowsingDirectory = null;
1834                                }
1835                        }
1836                } catch (SecurityException se) {
1837                        displayWarn(se.getClass().getName()
1838                                        + " in DefaultUploadPolicy.setCurrentBrowsingDirectory(): "
1839                                        + currentBrowsingDirectoryParam + " is ignored.");
1840                }
1841        }
1842
1843        /** @see UploadPolicy#getCurrentBrowsingDirectory() */
1844        public File getCurrentBrowsingDirectory() {
1845                return this.currentBrowsingDirectory;
1846        }
1847
1848        /** @see UploadPolicy#getDateFormat() */
1849        public String getDateFormat() {
1850                return UploadPolicy.DEFAULT_DATE_FORMAT;
1851        }
1852
1853        /** @see UploadPolicy#getDebugLevel() */
1854        public int getDebugLevel() {
1855                return this.debugLevel;
1856        }
1857
1858        /** @see UploadPolicy#setDebugLevel(int) */
1859        public void setDebugLevel(int debugLevel) {
1860                setDebugLevel(debugLevel, true);
1861        }
1862
1863        /**
1864         * Set the debug level.
1865         *
1866         * @param debugLevel
1867         *            The new debuglevel.
1868         * @param displayAppletParameterList
1869         *            Flag. If set to true, the applet's parameters are shown.
1870         */
1871        public synchronized void setDebugLevel(int debugLevel,
1872                        boolean displayAppletParameterList) {
1873                // If the debugLevel was previously set, we inform the user of this
1874                // change.
1875                if (this.debugLevel >= 0) {
1876                        displayInfo("Debug level set to " + debugLevel);
1877                        if (this.debugGenerateFile) {
1878                                displayInfo("Current debug output file: "
1879                                                + this.debugFile.getAbsolutePath());
1880                        }
1881                }
1882                this.debugLevel = debugLevel;
1883
1884                // Let's display the current applet parameters.
1885                if (displayAppletParameterList) {
1886                        displayParameterStatus();
1887                }
1888        }
1889
1890        /**
1891         * Getter for fileChooserIconFromFileContent.
1892         *
1893         * @return Current value for fileChooserIconFromFileContent
1894         * @see UploadPolicy#PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT
1895         */
1896        public int getFileChooserIconFromFileContent() {
1897                return this.fileChooserIconFromFileContent;
1898        }
1899
1900        /**
1901         * Setter for fileChooserIconFromFileContent. Current allowed values are:
1902         * -1, 0, 1. Default value is 0.
1903         *
1904         * @param fileChooserIconFromFileContent
1905         *            Value to be set. If the value is not allowed (not -1, 0 or 1),
1906         *            the current value is unchangeed.
1907         * @exception java.lang.IllegalArgumentException
1908         *                When a value not in -1, 0 1 is given.
1909         * @see UploadPolicy#PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT
1910         */
1911        public void setFileChooserIconFromFileContent(
1912                        int fileChooserIconFromFileContent) {
1913                if (fileChooserIconFromFileContent != -1
1914                                && fileChooserIconFromFileContent != 0
1915                                && fileChooserIconFromFileContent != 1) {
1916                        throw new java.lang.IllegalArgumentException(
1917                                        "fileChooserIconFromFileContent must be one of -1, 0, 1");
1918                }
1919                this.fileChooserIconFromFileContent = fileChooserIconFromFileContent;
1920        }
1921
1922        /**
1923         * Getter for fileChooserIconSize.
1924         *
1925         * @return Current value for fileChooserIconSize
1926         * @see UploadPolicy#PROP_FILE_CHOOSER_ICON_SIZE
1927         */
1928        public int getFileChooserIconSize() {
1929                return this.fileChooserIconSize;
1930        }
1931
1932        /**
1933         * Setter for fileChooserIconSize.
1934         *
1935         * @param fileChooserIconSize
1936         *            Value to be set.
1937         * @exception java.lang.IllegalArgumentException
1938         *                When a negative value is given.
1939         * @see UploadPolicy#PROP_FILE_CHOOSER_ICON_SIZE
1940         */
1941        public void setFileChooserIconSize(int fileChooserIconSize) {
1942                if (fileChooserIconSize <= 0) {
1943                        throw new java.lang.IllegalArgumentException(
1944                                        "fileChooserIconSize must be more than 0");
1945                }
1946                this.fileChooserIconSize = fileChooserIconSize;
1947        }
1948
1949        /** @see wjhk.jupload2.policies.UploadPolicy#setLang(String) */
1950        public void setLang(String lang) {
1951                this.lang = lang;
1952                if (lang == null) {
1953                        displayInfo("lang = null, taking default language");
1954                        locale = Locale.getDefault();
1955                } else {
1956                        // If we have a 5 characters lang string, then it should look like
1957                        // ll_CC, where ll is the language code
1958                        // and CC is the Country code.
1959                        if (lang.length() == 5
1960                                        && (lang.substring(2, 3).equals("_") || lang
1961                                                        .substring(2, 3).equals("-"))) {
1962                                String language = lang.substring(0, 2);
1963                                String country = lang.substring(3, 5);
1964                                displayDebug("setLang - language read: " + language, 50);
1965                                displayDebug("setLang - country read: " + country, 50);
1966                                locale = new Locale(language, country.toUpperCase());
1967                        } else {
1968                                locale = new Locale(lang);
1969                                displayDebug("setLang - language read (no country): " + lang,
1970                                                50);
1971                        }
1972                }
1973
1974                /*
1975                 * Patch given by Patrick Use of a specific class loader. The standard
1976                 * ResourceBundle checks first for a class that has the name of the
1977                 * resource bundle. Since there is no such class in the jar file, the
1978                 * AppletClassLoader makes a http request to the server, which will end
1979                 * with a 404 since there is no such class either. To avoid this
1980                 * unnecessary lookup we use a class loader that throws directly a
1981                 * ClassNotFoundException. After looking for a class (which is
1982                 * unsuccessful) ResourceBundle looks finally for a properties file.
1983                 * Therefore we delegate that lookup to the original class loader since
1984                 * this is in the jar file.
1985                 */
1986                this.resourceBundle = ResourceBundle.getBundle("lang.lang", locale,
1987                // Special class loader, see description above
1988                                new ClassLoader(this.getClass().getClassLoader()) {
1989                                        /** {@inheritDoc} */
1990                                        @Override
1991                                        public Class<?> loadClass(String name)
1992                                                        throws ClassNotFoundException {
1993                                                throw new ClassNotFoundException();
1994                                        }
1995
1996                                        /** {@inheritDoc} */
1997                                        @Override
1998                                        public InputStream getResourceAsStream(String name) {
1999                                                return this.getClass().getClassLoader()
2000                                                                .getResourceAsStream(name);
2001                                        }
2002                                });
2003        }
2004
2005        /** {@inheritDoc} */
2006        public Locale getLocale() {
2007                return this.locale;
2008        }
2009
2010        /**
2011     */
2012        protected String getLookAndFeel() {
2013                return this.lookAndFeel;
2014        }
2015
2016        /**
2017         * @param lookAndFeel
2018         *            the lookAndFeel to set
2019         */
2020        protected void setLookAndFeel(String lookAndFeel) {
2021                try {
2022                        this.lookAndFeel = lookAndFeel;
2023                        if (lookAndFeel != null && !lookAndFeel.equals("")
2024                                        && !lookAndFeel.equals("java")) {
2025                                // We try to call the UIManager.setLookAndFeel() method. We
2026                                // catch
2027                                // all possible exceptions, to prevent
2028                                // that the applet is blocked.
2029                                if (!lookAndFeel.equals("system")) {
2030                                        // Correction given by Fritz. Thanks to him.
2031                                        UIManager.setLookAndFeel(lookAndFeel);
2032                                } else {
2033                                        UIManager.setLookAndFeel(UIManager
2034                                                        .getSystemLookAndFeelClassName());
2035                                }
2036                        } else {
2037                                this.lookAndFeel = "java";
2038                                UIManager
2039                                                .setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
2040                        }
2041                } catch (Exception e) {
2042                        displayErr(e);
2043                        try {
2044                                this.lookAndFeel = "java";
2045                                UIManager
2046                                                .setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
2047                        } catch (UnsupportedLookAndFeelException e1) {
2048                                displayErr(e1);
2049                                // Hum, hum: we should not arrive here... We not a 'dummy' one.
2050                                this.lookAndFeel = null;
2051                        }
2052                }
2053        }
2054
2055        /** @see wjhk.jupload2.policies.UploadPolicy#getMaxChunkSize() */
2056        public long getMaxChunkSize() {
2057                return this.maxChunkSize;
2058        }
2059
2060        /**
2061         * If the given value is less or equals to 0, it is set back to
2062         * Long_MAX_VALUE.
2063         *
2064         * @param maxChunkSize
2065         *            the maxChunkSize to set
2066         */
2067        protected void setMaxChunkSize(long maxChunkSize) {
2068                if (maxChunkSize <= 0) {
2069                        displayDebug(
2070                                        "maxChunkSize<=0 which is invalid. Switched to the default value (Long.MAX_VALUE)",
2071                                        1);
2072                        maxChunkSize = Long.MAX_VALUE;
2073                }
2074                this.maxChunkSize = maxChunkSize;
2075        }
2076
2077        /** @see wjhk.jupload2.policies.UploadPolicy#getMaxFileSize() */
2078        public long getMaxFileSize() {
2079                return this.maxFileSize;
2080        }
2081
2082        /**
2083         * @param maxFileSize
2084         *            the maxFileSize to set
2085         */
2086        protected void setMaxFileSize(long maxFileSize) {
2087                if (maxFileSize <= 0) {
2088                        displayDebug(
2089                                        "maxFileSize<=0 which is invalid. Switched to the default value (Long.MAX_VALUE)",
2090                                        1);
2091                        maxFileSize = Long.MAX_VALUE;
2092                }
2093                this.maxFileSize = maxFileSize;
2094        }
2095
2096        /** @see wjhk.jupload2.policies.UploadPolicy#getNbFilesPerRequest() */
2097        public int getNbFilesPerRequest() {
2098                return this.nbFilesPerRequest;
2099        }
2100
2101        /**
2102         * @param nbFilesPerRequest
2103         *            the nbFilesPerRequest to set
2104         * @throws JUploadException
2105         */
2106        protected void setNbFilesPerRequest(int nbFilesPerRequest)
2107                        throws JUploadException {
2108                // If httpUploadParameterType is oneFile,
2109                if (getHttpUploadParameterType().equals(
2110                                UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)
2111                                && nbFilesPerRequest != 1) {
2112                        throw new JUploadException(
2113                                        "nbFilesPerRequest must be 1, when httpUploadParameterType is oneFile");
2114                }
2115
2116                if (nbFilesPerRequest < 1) {
2117                        displayDebug(
2118                                        "nbFilesPerRequest <1 : switched to the 'unlimited' value (Integer.MAX_VALUE)",
2119                                        1);
2120                        this.nbFilesPerRequest = Integer.MAX_VALUE;
2121                } else {
2122                        this.nbFilesPerRequest = nbFilesPerRequest;
2123                }
2124        }
2125
2126        /** @see UploadPolicy#getFilenameEncoding() */
2127        public String getFilenameEncoding() {
2128                return this.filenameEncoding;
2129        }
2130
2131        /** @see UploadPolicy#getFileFilterName() */
2132        public String getFileFilterName() {
2133                return this.fileFilterName;
2134        }
2135
2136        /**
2137         * @param fileFilterName
2138         *            The new name for the fileFilter
2139         * @see UploadPolicy#PROP_FILE_FILTER_NAME
2140         */
2141        protected void setFileFilterName(String fileFilterName) {
2142                this.fileFilterName = fileFilterName;
2143        }
2144
2145        /**
2146         * @param filenameEncoding
2147         *            the filenameEncoding to set
2148         */
2149        protected void setFilenameEncoding(String filenameEncoding) {
2150                if (filenameEncoding != null && filenameEncoding.equals("")) {
2151                        filenameEncoding = null;
2152                }
2153                if (filenameEncoding != null && !Charset.isSupported(filenameEncoding)) {
2154                        throw new UnsupportedCharsetException("non supported charset ("
2155                                        + filenameEncoding + ")");
2156                }
2157                this.filenameEncoding = filenameEncoding;
2158        }
2159
2160        /** @see UploadPolicy#getFtpCreateDirectoryStructure() */
2161        public boolean getFtpCreateDirectoryStructure() {
2162                return this.ftpCreateDirectoryStructure;
2163        }
2164
2165        /**
2166         * @param ftpCreateDirectoryStructure
2167         *            the ftpCreateDirectoryStructure to set
2168         */
2169        protected void setFtpCreateDirectoryStructure(
2170                        boolean ftpCreateDirectoryStructure) {
2171                this.ftpCreateDirectoryStructure = ftpCreateDirectoryStructure;
2172        }
2173
2174        /** @see UploadPolicy#getFtpTransfertBinary() */
2175        public boolean getFtpTransfertBinary() {
2176                return this.ftpTransfertBinary;
2177        }
2178
2179        /**
2180         * @param ftpTransfertBinary
2181         *            the ftpTransfertBinary to set
2182         */
2183        protected void setFtpTransfertBinary(boolean ftpTransfertBinary) {
2184                this.ftpTransfertBinary = ftpTransfertBinary;
2185        }
2186
2187        /** @see UploadPolicy#getFtpTransfertPassive() */
2188        public boolean getFtpTransfertPassive() {
2189                return this.ftpTransfertPassive;
2190        }
2191
2192        /**
2193         * @param ftpTransfertPassive
2194         *            the ftpTransfertPassive to set
2195         */
2196        protected void setFtpTransfertPassive(boolean ftpTransfertPassive) {
2197                this.ftpTransfertPassive = ftpTransfertPassive;
2198        }
2199
2200        /** @see wjhk.jupload2.policies.UploadPolicy#getPostURL() */
2201        public String getPostURL() {
2202                return this.postURL;
2203        }
2204
2205        /**
2206         * @throws JUploadException
2207         * @see wjhk.jupload2.policies.UploadPolicy#setPostURL(String)
2208         */
2209        public void setPostURL(String postURL) throws JUploadException {
2210                // Be more forgiving about postURL:
2211                // - If none is specified, use the original DocumentBase of the
2212                // applet.
2213                // - If a non-absolute URI (an URI without protocol and server) is
2214                // specified,
2215                // prefix it with "http://servername"
2216                // - If a relative URI is specified, prefix it with the DocumentBase's
2217                // parent
2218                this.postURL = this.juploadContext.normalizeURL(postURL);
2219        }
2220
2221        /** @see wjhk.jupload2.policies.UploadPolicy#getReadCookieFromNavigator() */
2222        public boolean getReadCookieFromNavigator() {
2223                return this.readCookieFromNavigator;
2224        }
2225
2226        /** @see wjhk.jupload2.policies.UploadPolicy#getReadCookieFromNavigator() */
2227        protected void setReadCookieFromNavigator(boolean readCookieFromNavigator) {
2228                this.readCookieFromNavigator = readCookieFromNavigator;
2229        }
2230
2231        /** @see wjhk.jupload2.policies.UploadPolicy#getReadUserAgentFromNavigator() */
2232        public boolean getReadUserAgentFromNavigator() {
2233                return this.readUserAgentFromNavigator;
2234        }
2235
2236        /** @see wjhk.jupload2.policies.UploadPolicy#getReadUserAgentFromNavigator() */
2237        protected void setReadUserAgentFromNavigator(
2238                        boolean readUserAgentFromNavigator) {
2239                this.readUserAgentFromNavigator = readUserAgentFromNavigator;
2240        }
2241
2242        /** @see UploadPolicy#getRetryMaxNumberOf() */
2243        public int getRetryMaxNumberOf() {
2244                return this.retryMaxNumberOf;
2245        }
2246
2247        /**
2248         * @param retryMaxNumberOf
2249         *            New value to set for the retryMaxNumberOf applet parameter
2250         * @exception IllegalArgumentException
2251         *                If retryMaxNumberOf is less than 0.
2252         * @see UploadPolicy#getRetryMaxNumberOf()
2253         */
2254        public void setRetryMaxNumberOf(int retryMaxNumberOf) {
2255                if (retryMaxNumberOf < 0) {
2256                        throw new IllegalArgumentException(
2257                                        "retryMaxNumberOf must be 0 or more");
2258                }
2259                this.retryMaxNumberOf = retryMaxNumberOf;
2260        }
2261
2262        /** @see UploadPolicy#getRetryNbSecondsBetween() */
2263        public int getRetryNbSecondsBetween() {
2264                return this.retryNbSecondsBetween;
2265        }
2266
2267        /**
2268         * @param retryNbSecondsBetween
2269         *            New value to set for the retryNbSecondsBetween applet
2270         *            parameter
2271         * @exception IllegalArgumentException
2272         *                If retryNbSecondsBetween is less than 0.
2273         * @see UploadPolicy#getRetryNbSecondsBetween()
2274         */
2275        public void setRetryNbSecondsBetween(int retryNbSecondsBetween) {
2276                if (retryNbSecondsBetween < 0) {
2277                        throw new IllegalArgumentException(
2278                                        "retryNbSecondsBetween must be 0 or more");
2279                }
2280                this.retryNbSecondsBetween = retryNbSecondsBetween;
2281        }
2282
2283        /** @see wjhk.jupload2.policies.UploadPolicy#getServerProtocol() */
2284        public String getServerProtocol() {
2285                if (this.serverProtocol == null) {
2286                        return DEFAULT_SERVER_PROTOCOL;
2287                } else {
2288                        return this.serverProtocol;
2289                }
2290        }
2291
2292        /** @see UploadPolicy#setServerProtocol(String) */
2293        public void setServerProtocol(String serverProtocol) {
2294                this.serverProtocol = serverProtocol;
2295        }
2296
2297        /** @see wjhk.jupload2.policies.UploadPolicy#getSendMD5Sum() */
2298        public boolean getSendMD5Sum() {
2299                return this.sendMD5Sum;
2300        }
2301
2302        /** @see UploadPolicy#setSendMD5Sum(boolean) */
2303        public void setSendMD5Sum(boolean sendMD5Sum) {
2304                this.sendMD5Sum = sendMD5Sum;
2305        }
2306
2307        /** @see wjhk.jupload2.policies.UploadPolicy#getShowLogWindow() */
2308        public String getShowLogWindow() {
2309                return this.showLogWindow;
2310        }
2311
2312        /** {@inheritDoc} */
2313        public void setShowLogWindow(String showLogWindow) {
2314                if (showLogWindow.equals(SHOWLOGWINDOW_TRUE)
2315                                || showLogWindow.equals(SHOWLOGWINDOW_FALSE)
2316                                || showLogWindow.equals(SHOWLOGWINDOW_ONERROR)) {
2317                        this.showLogWindow = showLogWindow;
2318                        // The log window may become visible or hidden, depending on this
2319                        // parameter.
2320                        if (this.juploadContext.getUploadPanel() != null) {
2321                                this.juploadContext.getUploadPanel().showOrHideLogWindow();
2322                        }
2323                } else {
2324                        displayWarn("[setShowLogWindow] Unallowed value: " + showLogWindow
2325                                        + " (showLogWindow is left unchanged)");
2326                }
2327        }
2328
2329        /** @see wjhk.jupload2.policies.UploadPolicy#getSpecificHeaders() */
2330        public String getSpecificHeaders() {
2331                return this.specificHeaders;
2332        }
2333
2334        /**
2335         * Set all specific headers defined in the specificHeaders applet parameter.
2336         * This string is splitted, so that each header is added to the headers
2337         * Vector. These headers are added to the headers list during applet
2338         * initialization. There is currently no automatic way to remove the headers
2339         * coming from specificHeaders, after initialization.
2340         *
2341         * @param specificHeaders
2342         */
2343        protected void setSpecificHeaders(String specificHeaders) {
2344                this.specificHeaders = specificHeaders;
2345                if (specificHeaders != null) {
2346                        // Let's add each header in specificHeaders to the headers list. In
2347                        // specificHeaders, each header is separated by the \n string (two
2348                        // characters: \ then n, not the \n character).
2349                        // The regexp to find the \n string (not the \n character) is: \\n
2350                        // We then double each \ character:
2351                        String[] headerArray = specificHeaders.split("\\\\n");
2352                        for (int x = 0; x < headerArray.length; x++) {
2353                                addHeader(headerArray[x]);
2354                        }
2355                }
2356        }
2357
2358        /**
2359         * @see wjhk.jupload2.policies.UploadPolicy#getSslVerifyCert()
2360         */
2361        public int getSslVerifyCert() {
2362                return this.sslVerifyCert;
2363        }
2364
2365        protected void setSslVerifyCert(String mode) throws JUploadException {
2366                int val = -1;
2367                if (mode.toLowerCase().equals("none"))
2368                        val = InteractiveTrustManager.NONE;
2369                if (mode.toLowerCase().equals("server"))
2370                        val = InteractiveTrustManager.SERVER;
2371                if (mode.toLowerCase().equals("client"))
2372                        val = InteractiveTrustManager.CLIENT;
2373                if (mode.toLowerCase().equals("strict"))
2374                        val = InteractiveTrustManager.STRICT;
2375                if (val == -1)
2376                        throw new JUploadException("Invalid parameter sslVerifyCert ("
2377                                        + mode + ")");
2378                this.sslVerifyCert = val;
2379        }
2380
2381        /**
2382         * @param show
2383         *            the new showStatusbar value
2384         */
2385        protected void setShowStatusbar(boolean show) {
2386                this.showStatusbar = show;
2387        }
2388
2389        /** @see wjhk.jupload2.policies.UploadPolicy#getStringUploadError() */
2390        public String getStringUploadError() {
2391                return this.stringUploadError;
2392        }
2393
2394        /** @see wjhk.jupload2.policies.UploadPolicy#getStringUploadSuccess() */
2395        public String getStringUploadSuccess() {
2396                return this.stringUploadSuccess;
2397        }
2398
2399        /** @see wjhk.jupload2.policies.UploadPolicy#getStringUploadWarning() */
2400        public String getStringUploadWarning() {
2401                return this.stringUploadWarning;
2402        }
2403
2404        /**
2405         * @param stringUploadError
2406         *            the stringUploadError to set
2407         * @throws JUploadException
2408         */
2409        protected void setStringUploadError(String stringUploadError)
2410                        throws JUploadException {
2411                this.stringUploadError = stringUploadError;
2412                if (stringUploadError != null) {
2413                        try {
2414                                this.patternError = Pattern.compile(stringUploadError);
2415                        } catch (PatternSyntaxException e) {
2416                                throw new JUploadException(
2417                                                "Invalid regex in parameter stringUploadError");
2418                        }
2419                }
2420        }
2421
2422        /**
2423         * @param stringUploadSuccess
2424         *            the stringUploadSuccess to set
2425         * @throws JUploadException
2426         */
2427        protected void setStringUploadSuccess(String stringUploadSuccess)
2428                        throws JUploadException {
2429                this.stringUploadSuccess = stringUploadSuccess;
2430                if (stringUploadSuccess != null) {
2431                        try {
2432                                this.patternSuccess = Pattern.compile(stringUploadSuccess);
2433                        } catch (PatternSyntaxException e) {
2434                                throw new JUploadException(
2435                                                "Invalid regex in parameter stringUploadSuccess");
2436                        }
2437                }
2438        }
2439
2440        /**
2441         * @param stringUploadWarning
2442         *            the stringUploadWarning to set
2443         * @throws JUploadException
2444         */
2445        protected void setStringUploadWarning(String stringUploadWarning)
2446                        throws JUploadException {
2447                this.stringUploadWarning = stringUploadWarning;
2448                if (stringUploadWarning != null) {
2449                        try {
2450                                this.patternWarning = Pattern.compile(stringUploadWarning);
2451                        } catch (PatternSyntaxException e) {
2452                                throw new JUploadException(
2453                                                "Invalid regex in parameter stringUploadWarning");
2454                        }
2455                }
2456        }
2457
2458        /** @see wjhk.jupload2.policies.UploadPolicy#getUrlToSendErrorTo() */
2459        public String getUrlToSendErrorTo() {
2460                return this.urlToSendErrorTo;
2461        }
2462
2463        /** {@inheritDoc} */
2464        public void setUrlToSendErrorTo(String urlToSendErrorTo)
2465                        throws JUploadException {
2466                if (null == urlToSendErrorTo)
2467                        return;
2468                String tmp = this.juploadContext.normalizeURL(urlToSendErrorTo);
2469                if (tmp.startsWith("ftp://")) {
2470                        throw new JUploadException(
2471                                        "urlToSendErrorTo: ftp scheme not supported.");
2472                }
2473                this.urlToSendErrorTo = tmp;
2474        }
2475
2476        /** @see wjhk.jupload2.policies.UploadPolicy#getFormdata() */
2477        public String getFormdata() {
2478                return this.formData;
2479        }
2480
2481        /** @see wjhk.jupload2.policies.UploadPolicy#getAfterUploadTarget() */
2482        public String getAfterUploadTarget() {
2483                return this.afterUploadTarget;
2484        }
2485
2486        // //////////////////////////////////////////////////////////////////////////////////////////////
2487        // /////////////////// Internal methods
2488        // //////////////////////////////////////////////////////////////////////////////////////////////
2489
2490        /**
2491         * Delete the current log. (called upon applet termination)
2492         */
2493        public synchronized void deleteLog() {
2494                if (this.debugGenerateFile) {
2495                        try {
2496                                if (null != this.debugOut) {
2497                                        this.debugOut.close();
2498                                        this.debugOut = null;
2499                                }
2500                                if (null != this.debugFile) {
2501                                        if (!this.debugFile.delete()) {
2502                                                displayWarn(this.debugFile.getName()
2503                                                                + " was not correctly removed!");
2504                                        }
2505                                        this.debugFile = null;
2506                                }
2507                        } catch (Exception e) {
2508                                // nothing to do: we mask the exception.
2509                                displayWarn(e.getClass().getName()
2510                                                + " occured in deleteLog(). Exception ignored.");
2511                        }
2512                }
2513        }
2514
2515        /**
2516         * This methods allows the applet to store all messages (debug, warning,
2517         * info, errors...) into a StringBuffer. If any problem occurs, the whole
2518         * output (displayed or not by the displayDebug, for instance) can be stored
2519         * in a file, or sent to the webmaster. This can help to identify and
2520         * correct problems that can occurs on the various computer configurations.
2521         *
2522         * @param msg
2523         */
2524        protected synchronized void addMsgToDebugLog(String msg) {
2525                // If uploading lots of chunks, the buffer gets too large, resulting in
2526                // a OutOfMemoryError on the heap so we now use a temporary file for the
2527                // debug log.
2528                if (this.debugGenerateFile && this.debugOk) {
2529                        try {
2530                                if (null == this.debugOut) {
2531                                        this.juploadContext.registerUnload(this, "deleteLog");
2532                                        this.debugFile = File
2533                                                        .createTempFile("jupload_", "_log.txt");
2534                                        this.debugOut = new PrintStream(new FileOutputStream(
2535                                                        this.debugFile));
2536                                }
2537                                boolean endsLF = msg.endsWith("\n");
2538                                msg = msg.replaceAll("\n", this.CRLF);
2539                                if (endsLF) {
2540                                        this.debugOut.print(msg);
2541                                } else {
2542                                        this.debugOut.println(msg);
2543                                }
2544                        } catch (IOException e) {
2545                                this.debugOk = false;
2546                                System.err.println("IO error on debuglog "
2547                                                + this.debugFile.getPath()
2548                                                + "\nFallback to standard output.");
2549                                System.out.println(msg);
2550                        }
2551                } else {
2552                        System.out.println(msg);
2553                }
2554        }
2555
2556        /**
2557         * Displays a message. If the logWindow panel is set, the message is
2558         * displayed on it. If not, the System.out.println function is used.
2559         *
2560         * @param msg
2561         *            The message to display.
2562         */
2563        private void displayMsg(String tag, String msg) {
2564                String message;
2565
2566                if (this.juploadContext.getLogWindow() == null) {
2567                        message = tag + " - " + msg;
2568                        System.out.println(message);
2569                } else {
2570                        message = this.juploadContext.getLogWindow().displayMsg(tag, msg);
2571                }
2572                // Let's store all text in the debug logfile
2573                if (this.debugGenerateFile) {
2574                        addMsgToDebugLog(message);
2575                }
2576        }
2577
2578        /**
2579         * Default reaction after a successful drop operation: no action.
2580         *
2581         * @see UploadPolicy#afterFileDropped(DropTargetDropEvent)
2582         */
2583        public void afterFileDropped(DropTargetDropEvent dropEvent) {
2584                // Default: no action.
2585        }
2586
2587        /**
2588         * Default implementation for {@link UploadPolicy#createFileChooser()}: just
2589         * a creation of a {@link JUploadFileChooser}.
2590         *
2591         * @see UploadPolicy#createFileChooser()
2592         */
2593        public JUploadFileChooser createFileChooser() {
2594                return new JUploadFileChooser(this);
2595        }
2596
2597        /**
2598         * This method returns the response for the
2599         * {@link JUploadFileFilter#accept(File)} which just calls this method. This
2600         * method checks that the file extension corresponds to the
2601         * allowedFileExtensions applet parameter.
2602         *
2603         * @see UploadPolicy#fileFilterAccept(File)
2604         */
2605        public boolean fileFilterAccept(File file) {
2606                if (file.isDirectory()) {
2607                        return true;
2608                } else if (this.allowedFileExtensions == null
2609                                || this.allowedFileExtensions.equals("")) {
2610                        return true;
2611                } else {
2612                        // Get the file extension
2613                        String extension = DefaultFileData.getExtension(file).toLowerCase();
2614                        // allowedFileExtensions is :
2615                        // - a list of file extensions,
2616                        // - in lower case,
2617                        // - separated by slash
2618                        // - A slash has been added at the beginning in
2619                        // setAllowedFileExtensions
2620                        // - A slash has been added at the end in setAllowedFileExtensions
2621                        // So, we just look for the /ext/ string in the stored
2622                        // allowedFileExtensions.
2623                        return (this.allowedFileExtensions.indexOf("/" + extension + "/")) >= 0;
2624                }
2625        }
2626
2627        /** @see UploadPolicy#fileFilterGetDescription() */
2628        public String fileFilterGetDescription() {
2629                if (this.allowedFileExtensions == null
2630                                || this.allowedFileExtensions.equals("")) {
2631                        return null;
2632                } else if (getFileFilterName() != null) {
2633                        return getFileFilterName();
2634                } else {
2635                        return "JUpload file filter (" + this.allowedFileExtensions + ")";
2636                }
2637        }
2638
2639        /**
2640         * Returns null: the default icon is used.
2641         *
2642         * @see UploadPolicy#fileViewGetIcon(File)
2643         */
2644        public Icon fileViewGetIcon(File file) {
2645                return null;
2646        }
2647
2648        /** @see wjhk.jupload2.policies.UploadPolicy#getLastException() */
2649        public JUploadException getLastException() {
2650                return this.lastException;
2651        }
2652
2653        /**
2654         * Set the last exception.
2655         *
2656         * @param exception
2657         *            The last exception that occurs into the applet.
2658         */
2659        public void setLastException(JUploadException exception) {
2660                this.lastException = exception;
2661
2662                // The log window may become visible.
2663                if (this.juploadContext.getUploadPanel() != null) {
2664                        this.juploadContext.getUploadPanel().showOrHideLogWindow();
2665                }
2666
2667        }
2668
2669        /** @see wjhk.jupload2.policies.UploadPolicy#getLastResponseBody() */
2670        public String getLastResponseBody() {
2671                return this.lastResponseBody;
2672        }
2673
2674        /** @see wjhk.jupload2.policies.UploadPolicy#getLastResponseMessage() */
2675        public String getLastResponseMessage() {
2676                return (null != this.lastResponseMessage) ? this.lastResponseMessage
2677                                : "";
2678        }
2679
2680        /**
2681         * @return The cursor that was active before setting the new one. Can be
2682         *         used to restore its previous state.
2683         * @see UploadPolicy#setCursor(Cursor)
2684         */
2685        public Cursor setCursor(Cursor cursor) {
2686                return this.juploadContext.setCursor(cursor);
2687        }
2688
2689        /**
2690         * @return The cursor that was active before setting the new one. Can be
2691         *         used to restore its previous state.
2692         * @see UploadPolicy#setWaitCursor()
2693         */
2694        public Cursor setWaitCursor() {
2695                return this.juploadContext.setWaitCursor();
2696        }
2697
2698}
Note: See TracBrowser for help on using the repository browser.