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

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

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

Line 
1//
2// $Id: FileUploadThreadFTP.java 136 2007-05-12 20:15:36 +0000 (sam., 12 mai
3// 2007) etienne_sf $
4//
5// jupload - A file upload applet.
6// Copyright 2007 The JUpload Team
7//
8// Created: 2007-12-11
9// Creator: etienne_sf
10// Last modified: $Date: 2007-07-21 09:42:51 +0200 (sam., 21 juil. 2007) $
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.upload.helper;
23
24import java.io.ByteArrayOutputStream;
25import java.io.IOException;
26import java.io.OutputStreamWriter;
27import java.io.UnsupportedEncodingException;
28import java.io.Writer;
29
30import wjhk.jupload2.exception.JUploadIOException;
31import wjhk.jupload2.policies.UploadPolicy;
32
33/**
34 * This class is a utility, which provide easy encoding for HTTP queries. The
35 * way to use this class is:
36 * <OL TYPE=1>
37 * <LI>Instantiate a new object
38 * <LI>Append data to it, using the append methods. Available for: String,
39 * byte[], other ByteArrayEncode...
40 * <LI>Close the stream. This will prevent any new data to be appended to it.
41 * The encoded length can now be calculated.
42 * <LI>Get the encoded length.
43 * <LI>Get the encoded byte array
44 * </OL>
45 *
46 * @author etienne_sf
47 *
48 */
49
50public class ByteArrayEncoderHTTP implements ByteArrayEncoder {
51
52    /**
53     * The default encoding. It can be retrieved with
54     * {@link #getDefaultEncoding()}.
55     */
56    final static String DEFAULT_ENCODING = "UTF-8";
57
58    /**
59     * The boundary, to put between to post variables. Can not be changed during
60     * the object 'life'.
61     */
62    private String bound = null;
63
64    /**
65     * The current encoding. Can not be changed during the object 'life'.
66     */
67    private String encoding = DEFAULT_ENCODING;
68
69    /**
70     * Indicate whether the encoder is closed or not. If closed, it's impossible
71     * to append new data to it. If not closed, it's impossible to get the
72     * encoded length or the encoded byte array.<BR>
73     * <B>Note:</B> a closed byte array can not be re-opened.
74     */
75    boolean closed = false;
76
77    /**
78     * The actual array, which will collect the encoded bytes.
79     */
80    private ByteArrayOutputStream baos = new ByteArrayOutputStream();
81
82    /**
83     * The byte array length. Calculated when the ByteArrayOutput is closed.
84     */
85    private int encodedLength = -1;
86
87    /**
88     * The encoded byte array. Calculated when the ByteArrayOutput is closed.
89     */
90    private byte[] encodedByteArray = null;
91
92    /**
93     * The current upload policy.
94     */
95    private UploadPolicy uploadPolicy;
96
97    /**
98     * The writer, that will encode the input parameters to {@link #baos}.
99     */
100    private Writer writer;
101
102    // ///////////////////////////////////////////////////////////////////////
103    // //////////////// VARIOUS UTILITIES ////////////////////////////////////
104    // ///////////////////////////////////////////////////////////////////////
105
106    // ///////////////////////////////////////////////////////////////////////
107    // //////////////// CONSTRUCTORS /////////////////////////////////////////
108    // ///////////////////////////////////////////////////////////////////////
109
110    /**
111     * Create an encoder, using the DEFAULT_ENCODING encoding.
112     *
113     * @param uploadPolicy The current upload policy
114     * @throws JUploadIOException Any IO exception
115     */
116    public ByteArrayEncoderHTTP(UploadPolicy uploadPolicy)
117            throws JUploadIOException {
118        init(uploadPolicy, null, DEFAULT_ENCODING);
119    }
120
121    /**
122     * Create an encoder, and specifies the encoding to use.
123     *
124     * @param uploadPolicy The current upload policy
125     * @param bound Any specific boundary. May be null: in this case a default
126     *            boundary is used.
127     * @throws JUploadIOException Any IO exception
128     */
129    public ByteArrayEncoderHTTP(UploadPolicy uploadPolicy, String bound)
130            throws JUploadIOException {
131        init(uploadPolicy, bound, DEFAULT_ENCODING);
132    }
133
134    /**
135     * Create an encoder, and specifies the boundary and encoding to use.
136     *
137     * @param uploadPolicy The current upload policy
138     * @param bound Any specific boundary. May be null: in this case a default
139     *            boundary is used.
140     * @param encoding The encoding to use. For instance, "UTF-8".
141     * @throws JUploadIOException Any IO exception
142     */
143    public ByteArrayEncoderHTTP(UploadPolicy uploadPolicy, String bound,
144            String encoding) throws JUploadIOException {
145        init(uploadPolicy, bound, encoding);
146    }
147
148    // ///////////////////////////////////////////////////////////////////////
149    // //////////////// Public methods ///////////////////////////////////////
150    // ///////////////////////////////////////////////////////////////////////
151
152    /**
153     * @throws JUploadIOException
154     * @see wjhk.jupload2.upload.helper.ByteArrayEncoder#close()
155     */
156    synchronized public void close() throws JUploadIOException {
157        if (isClosed()) {
158            throw new JUploadIOException(
159                    "Trying to close an already closed ByteArrayEncoded");
160        }
161        try {
162            this.writer.close();
163        } catch (IOException e) {
164            throw new JUploadIOException(e);
165        }
166        this.encodedByteArray = this.baos.toByteArray();
167        this.encodedLength = this.encodedByteArray.length;
168        this.closed = true;
169    }
170
171    /** {@inheritDoc} */
172    public ByteArrayEncoder append(String str) throws JUploadIOException {
173        try {
174            this.writer.append(str);
175        } catch (IOException e) {
176            throw new JUploadIOException(e);
177        }
178        // Returning the encoder allows calls like:
179        // bae.append("qdqd").append("qsldqd"); (like StringBuffer)
180        return this;
181    }
182
183    /** {@inheritDoc} */
184    public ByteArrayEncoder append(int b) throws JUploadIOException {
185        try {
186            this.writer.flush();
187            this.baos.write(b);
188        } catch (IOException e) {
189            throw new JUploadIOException(e);
190        }
191        // Returning the encoder allows calls like:
192        // bae.append("qdqd").append("qsldqd"); (like StringBuffer)
193        return this;
194    }
195
196    /** {@inheritDoc} */
197    public ByteArrayEncoder append(byte[] b) throws JUploadIOException {
198        try {
199            this.writer.flush();
200            this.baos.write(b);
201        } catch (IOException e) {
202            throw new JUploadIOException(e);
203        }
204        // Returning the encoder allows calls like:
205        // bae.append("qdqd").append("qsldqd"); (like StringBuffer)
206        return this;
207    }
208
209    /** {@inheritDoc} */
210    public ByteArrayEncoder append(ByteArrayEncoder bae)
211            throws JUploadIOException {
212        this.append(bae.getEncodedByteArray());
213
214        return this;
215    }
216
217    /** {@inheritDoc} */
218    public ByteArrayEncoder appendTextProperty(String name, String value,
219            int index) throws JUploadIOException {
220        String propertySuffix = "";
221        // if an index is given, we may have to suffix the name of the upload
222        // parameter, depending on the value of httpUploadParameterType
223        if (index >= 0) {
224            if (this.uploadPolicy.getHttpUploadParameterType().equals(
225                    UploadPolicy.HTTPUPLOADPARAMETERTYPE_ARRAY)) {
226                propertySuffix = "[]";
227            } else if (this.uploadPolicy.getHttpUploadParameterType().equals(
228                    UploadPolicy.HTTPUPLOADPARAMETERTYPE_ITERATION)) {
229                propertySuffix = Integer.toString(index);
230            }
231        }
232        this.append(this.bound).append("\r\n");
233        this.append("Content-Disposition: form-data; name=\"").append(name)
234                .append(propertySuffix).append("\"\r\n");
235        this.append("Content-Transfer-Encoding: 8bit\r\n");
236        this.append("Content-Type: text/plain; charset=").append(this.getEncoding())
237                .append("\r\n");
238        // An empty line before the actual value.
239        this.append("\r\n");
240        // And then, the value!
241        this.append(value).append("\r\n");
242
243        return this;
244    }
245
246    /** {@inheritDoc} */
247    public ByteArrayEncoder appendEndPropertyList() throws JUploadIOException {
248        this.append(this.bound).append("--\r\n");
249        return this;
250    }
251
252    /** {@inheritDoc} */
253    public ByteArrayEncoder appendFormVariables(String formname)
254            throws JUploadIOException {
255        String action = "Entering ByteArrayEncoderHTTP.appendFormVariables() [html form: "
256                + formname + "]";
257        try {
258            this.uploadPolicy.displayDebug(action, 80);
259            // TODO Do not use getApplet() anymore, here.
260            action = "win = netscape.javascript.JSObject.getWindow";
261            netscape.javascript.JSObject win = netscape.javascript.JSObject
262                    .getWindow(this.uploadPolicy.getContext().getApplet());
263
264            action = "o = win.eval";
265            Object o = win.eval("document.forms[\"" + formname
266                    + "\"].elements.length");
267            if (o instanceof Number) {
268                int len = ((Number) o).intValue();
269                if (len <= 0) {
270                    this.uploadPolicy.displayWarn("The specified form \""
271                            + formname + "\" does not contain any elements.");
272                }
273                int i;
274                for (i = 0; i < len; i++) {
275                    try {
276                        action = "name = win.eval";
277                        Object name = win.eval("document.forms[\"" + formname
278                                + "\"][" + i + "].name");
279                        action = "value = win.eval";
280                        Object value = win.eval("document.forms[\"" + formname
281                                + "\"][" + i + "].value");
282                        action = "elementType = win.eval";
283                        Object elementType = win.eval("document.forms[\""
284                                + formname + "\"][" + i + "].type");
285                        action = "elementClass = win.eval";
286                        // elementClass seems to be not supported by IE7
287                        // The next line prevents formData to be sent to the
288                        // server, when formData is used on IE7. Works fine with
289                        // firefox.
290                        // Object elementClass = win.eval("document." + formname
291                        // + "[" + i + "].class");
292                        action = "etype = win.eval";
293                        Object etype = win.eval("document.forms[\"" + formname
294                                + "\"][" + i + "].type");
295                        if (etype instanceof String) {
296                            String t = (String) etype;
297                            if (t.equals("checkbox") || t.equals("radio")) {
298                                action = "on = win.eval";
299                                Object on = win.eval("document.forms[\""
300                                        + formname + "\"][" + i + "].checked");
301                                if (on instanceof Boolean) {
302                                    // Skip unchecked checkboxes and
303                                    // radiobuttons
304                                    if (!((Boolean) on).booleanValue()) {
305                                        this.uploadPolicy
306                                                .displayDebug(
307                                                        "  [ByteArrayEncoder.appendFormVariables] Skipping unchecked checkboxes and radiobuttons",
308                                                        80);
309                                        // TODO Do not use getApplet() anymore,
310                                        // here.
311                                        continue;
312                                    }
313                                }
314                            }
315                        }
316                        if (name instanceof String
317                                && ((String) name).length() > 0) {
318                            if (value instanceof String) {
319                                this.uploadPolicy.displayDebug(
320                                        "  [ByteArrayEncoder.appendFormVariables] Adding formdata element num "
321                                                + i + " (name: " + name
322                                                + ", value: " + value
323                                                + ", type: " + elementType
324                                                /* + ", class: " + elementClass */
325                                                + ")", 80);
326                                this.appendTextProperty((String) name,
327                                        (String) value, -1);
328                            } else {
329                                this.uploadPolicy
330                                        .displayWarn("  [ByteArrayEncoder.appendFormVariables] Value must be an instance of String (name: "
331                                                + name
332                                                + ", value: )"
333                                                + value
334                                                + ")");
335                            }
336                        } else {
337                            this.uploadPolicy
338                                    .displayWarn("  [ByteArrayEncoder.appendFormVariables] Name must be an instance of String (name: "
339                                            + name + ", value: )" + value + ")");
340                        }
341                    } catch (netscape.javascript.JSException e1) {
342                        this.uploadPolicy
343                                .displayWarn(e1.getStackTrace()[1]
344                                        + ": got JSException in ByteArrayEncoderHTTP.appendFormVariables() [html form: "
345                                        + formname
346                                        + "] - bailing out (action: " + action
347                                        + ")");
348                        i = len;
349                    }
350                }
351            } else {
352                this.uploadPolicy
353                        .displayWarn("  [ByteArrayEncoder.appendFormVariables] The specified form \""
354                                + formname
355                                + "\" could not be found (or has no element).");
356            }
357        } catch (netscape.javascript.JSException e) {
358            this.uploadPolicy.displayDebug(e.getStackTrace()[1]
359                    + ": No JavaScript available (action: " + action + ")", 10);
360        }
361
362        this.uploadPolicy
363                .displayDebug(
364                        "  [ByteArrayEncoder.appendFormVariables] End of ByteArrayEncoderHTTP.appendFormVariables()",
365                        80);
366        return this;
367    }
368
369    /** {@inheritDoc} */
370    public String getBoundary() {
371        return this.bound;
372    }
373
374    /**
375     * @return value of the DEFAULT_ENCODING constant.
376     */
377    public static String getDefaultEncoding() {
378        return DEFAULT_ENCODING;
379    }
380
381    /** {@inheritDoc} */
382    public boolean isClosed() {
383        return this.closed;
384    }
385
386    /** {@inheritDoc} */
387    public String getEncoding() {
388        return this.encoding;
389    }
390
391    /** {@inheritDoc} */
392    public int getEncodedLength() throws JUploadIOException {
393        if (!isClosed()) {
394            throw new JUploadIOException(
395                    "Trying to get length of a on non-closed ByteArrayEncoded");
396        }
397        return this.encodedLength;
398    }
399
400    /** {@inheritDoc} */
401    public byte[] getEncodedByteArray() throws JUploadIOException {
402        if (!isClosed()) {
403            throw new JUploadIOException(
404                    "Trying to get the byte array of a on non-closed ByteArrayEncoded");
405        }
406        return this.encodedByteArray;
407    }
408
409    /** {@inheritDoc} */
410    public String getString() throws JUploadIOException {
411        if (!isClosed()) {
412            throw new JUploadIOException(
413                    "Trying to get the byte array of a on non-closed ByteArrayEncoded");
414        }
415        try {
416            return new String(this.encodedByteArray, getEncoding());
417        } catch (UnsupportedEncodingException e) {
418            throw new JUploadIOException(e);
419        }
420    }
421
422    // ///////////////////////////////////////////////////////////////////////
423    // //////////////// Private methods //////////////////////////////////////
424    // ///////////////////////////////////////////////////////////////////////
425
426    /**
427     * Initialization: called by the constructors.
428     *
429     * @throws JUploadIOException
430     */
431    private void init(UploadPolicy uploadPolicy, String bound, String encoding)
432            throws JUploadIOException {
433        this.uploadPolicy = uploadPolicy;
434        this.encoding = encoding;
435        this.bound = bound;
436
437        try {
438            this.writer = new OutputStreamWriter(this.baos, encoding);
439        } catch (UnsupportedEncodingException e) {
440            throw new JUploadIOException(e);
441        }
442    }
443}
Note: See TracBrowser for help on using the repository browser.