Source Code Cross Referenced for MultipartParser.java in  » Web-Framework » cocoon » org » apache » cocoon » servlet » multipart » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Framework » cocoon » org.apache.cocoon.servlet.multipart 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         * 
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         * 
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.cocoon.servlet.multipart;
018:
019:        import java.io.BufferedInputStream;
020:        import java.io.ByteArrayInputStream;
021:        import java.io.ByteArrayOutputStream;
022:        import java.io.File;
023:        import java.io.FileOutputStream;
024:        import java.io.IOException;
025:        import java.io.InputStream;
026:        import java.io.OutputStream;
027:        import java.io.PushbackInputStream;
028:        import java.util.Enumeration;
029:        import java.util.Hashtable;
030:        import java.util.StringTokenizer;
031:        import java.util.Vector;
032:
033:        import javax.servlet.http.HttpServletRequest;
034:        import javax.servlet.http.HttpSession;
035:
036:        import org.apache.cocoon.util.NullOutputStream;
037:
038:        /**
039:         * This class is used to implement a multipart request wrapper.
040:         * It will parse the http post stream and and fill it's hashtable with values.
041:         *
042:         * The hashtable will contain:
043:         * Vector: inline part values
044:         * FilePart: file part
045:         *
046:         * @author <a href="mailto:j.tervoorde@home.nl">Jeroen ter Voorde</a>
047:         * @version CVS $Id: MultipartParser.java 479303 2006-11-26 06:56:17Z antonio $
048:         */
049:        public class MultipartParser {
050:
051:            public static final String UPLOAD_STATUS_SESSION_ATTR = "org.apache.cocoon.servlet.multipartparser.status";
052:
053:            private final static int FILE_BUFFER_SIZE = 4096;
054:
055:            private static final int MAX_BOUNDARY_SIZE = 128;
056:
057:            private boolean saveUploadedFilesToDisk;
058:
059:            private File uploadDirectory = null;
060:
061:            private boolean allowOverwrite;
062:
063:            private boolean silentlyRename;
064:
065:            private int maxUploadSize;
066:
067:            private String characterEncoding;
068:
069:            private Hashtable parts;
070:
071:            private boolean oversized = false;
072:
073:            private int contentLength;
074:
075:            private HttpSession session;
076:
077:            private boolean hasSession;
078:
079:            private Hashtable uploadStatus;
080:
081:            /**
082:             * Constructor, parses given request
083:             *
084:             * @param saveUploadedFilesToDisk Write fileparts to the uploadDirectory. If true the corresponding object
085:             *              in the hashtable will contain a FilePartFile, if false a FilePartArray
086:             * @param uploadDirectory The directory to write to if saveUploadedFilesToDisk is true.
087:             * @param allowOverwrite Allow existing files to be overwritten.
088:             * @param silentlyRename If file exists rename file (using filename+number).
089:             * @param maxUploadSize The maximum content length accepted.
090:             * @param characterEncoding The character encoding to be used.
091:             */
092:            public MultipartParser(boolean saveUploadedFilesToDisk,
093:                    File uploadDirectory, boolean allowOverwrite,
094:                    boolean silentlyRename, int maxUploadSize,
095:                    String characterEncoding) {
096:                this .saveUploadedFilesToDisk = saveUploadedFilesToDisk;
097:                this .uploadDirectory = uploadDirectory;
098:                this .allowOverwrite = allowOverwrite;
099:                this .silentlyRename = silentlyRename;
100:                this .maxUploadSize = maxUploadSize;
101:                this .characterEncoding = characterEncoding;
102:            }
103:
104:            private void parseParts(int contentLength, String contentType,
105:                    InputStream requestStream) throws IOException,
106:                    MultipartException {
107:                this .contentLength = contentLength;
108:                if (contentLength > this .maxUploadSize) {
109:                    this .oversized = true;
110:                }
111:
112:                BufferedInputStream bufferedStream = new BufferedInputStream(
113:                        requestStream);
114:                PushbackInputStream pushbackStream = new PushbackInputStream(
115:                        bufferedStream, MAX_BOUNDARY_SIZE);
116:                TokenStream stream = new TokenStream(pushbackStream);
117:
118:                parseMultiPart(stream, getBoundary(contentType));
119:
120:            }
121:
122:            public Hashtable getParts(int contentLength, String contentType,
123:                    InputStream requestStream) throws IOException,
124:                    MultipartException {
125:                this .parts = new Hashtable();
126:                parseParts(contentLength, contentType, requestStream);
127:                return this .parts;
128:            }
129:
130:            public Hashtable getParts(HttpServletRequest request)
131:                    throws IOException, MultipartException {
132:                this .parts = new Hashtable();
133:
134:                // Copy all parameters coming from the request URI to the parts table.
135:                // This happens when a form's action attribute has some parameters
136:                Enumeration names = request.getParameterNames();
137:                while (names.hasMoreElements()) {
138:                    String name = (String) names.nextElement();
139:                    String[] values = request.getParameterValues(name);
140:                    Vector v = new Vector(values.length);
141:                    for (int i = 0; i < values.length; i++) {
142:                        v.add(values[i]);
143:                    }
144:                    this .parts.put(name, v);
145:                }
146:
147:                // upload progress bar support
148:                this .session = request.getSession();
149:                this .hasSession = this .session != null;
150:                if (this .hasSession) {
151:                    this .uploadStatus = new Hashtable();
152:                    this .uploadStatus.put("started", Boolean.FALSE);
153:                    this .uploadStatus.put("finished", Boolean.FALSE);
154:                    this .uploadStatus.put("sent", new Integer(0));
155:                    this .uploadStatus.put("total", new Integer(request
156:                            .getContentLength()));
157:                    this .uploadStatus.put("filename", "");
158:                    this .uploadStatus.put("error", Boolean.FALSE);
159:                    this .uploadStatus.put("uploadsdone", new Integer(0));
160:                    this .session.setAttribute(UPLOAD_STATUS_SESSION_ATTR,
161:                            this .uploadStatus);
162:                }
163:
164:                parseParts(request.getContentLength(),
165:                        request.getContentType(), request.getInputStream());
166:
167:                if (this .hasSession) {
168:                    this .uploadStatus.put("finished", Boolean.TRUE);
169:                }
170:
171:                return this .parts;
172:            }
173:
174:            /**
175:             * Parse a multipart block
176:             *
177:             * @param ts
178:             * @param boundary
179:             *
180:             * @throws IOException
181:             * @throws MultipartException
182:             */
183:            private void parseMultiPart(TokenStream ts, String boundary)
184:                    throws IOException, MultipartException {
185:
186:                ts.setBoundary(boundary.getBytes());
187:                ts.read(); // read first boundary away
188:                ts.setBoundary(("\r\n" + boundary).getBytes());
189:
190:                while (ts.getState() == TokenStream.STATE_NEXTPART) {
191:                    ts.nextPart();
192:                    parsePart(ts);
193:                }
194:
195:                if (ts.getState() != TokenStream.STATE_ENDMULTIPART) { // sanity check
196:                    throw new MultipartException("Malformed stream");
197:                }
198:            }
199:
200:            /**
201:             * Parse a single part
202:             *
203:             * @param ts
204:             *
205:             * @throws IOException
206:             * @throws MultipartException
207:             */
208:            private void parsePart(TokenStream ts) throws IOException,
209:                    MultipartException {
210:
211:                Hashtable headers = new Hashtable();
212:                headers = readHeaders(ts);
213:                try {
214:                    if (headers.containsKey("filename")) {
215:                        if (!"".equals(headers.get("filename"))) {
216:                            parseFilePart(ts, headers);
217:                        } else {
218:                            // IE6 sends an empty part with filename="" for
219:                            // empty upload fields. Just parse away the part
220:                            byte[] buf = new byte[32];
221:                            while (ts.getState() == TokenStream.STATE_READING)
222:                                ts.read(buf);
223:                        }
224:                    } else if (((String) headers.get("content-disposition"))
225:                            .toLowerCase().equals("form-data")) {
226:                        parseInlinePart(ts, headers);
227:                    }
228:
229:                    // FIXME: multipart/mixed parts are untested.
230:                    else if (((String) headers.get("content-disposition"))
231:                            .toLowerCase().indexOf("multipart") > -1) {
232:                        parseMultiPart(new TokenStream(ts, MAX_BOUNDARY_SIZE),
233:                                "--" + (String) headers.get("boundary"));
234:                        ts.read(); // read past boundary
235:                    } else {
236:                        throw new MultipartException("Unknown part type");
237:                    }
238:                } catch (IOException e) {
239:                    throw new MultipartException("Malformed stream: "
240:                            + e.getMessage());
241:                } catch (NullPointerException e) {
242:                    e.printStackTrace();
243:                    throw new MultipartException("Malformed header");
244:                }
245:            }
246:
247:            /**
248:             * Parse a file part
249:             *
250:             * @param in
251:             * @param headers
252:             *
253:             * @throws IOException
254:             * @throws MultipartException
255:             */
256:            private void parseFilePart(TokenStream in, Hashtable headers)
257:                    throws IOException, MultipartException {
258:
259:                byte[] buf = new byte[FILE_BUFFER_SIZE];
260:                OutputStream out;
261:                File file = null;
262:
263:                if (oversized) {
264:                    out = new NullOutputStream();
265:                } else if (!saveUploadedFilesToDisk) {
266:                    out = new ByteArrayOutputStream();
267:                } else {
268:                    String fileName = (String) headers.get("filename");
269:                    if (File.separatorChar == '\\')
270:                        fileName = fileName.replace('/', '\\');
271:                    else
272:                        fileName = fileName.replace('\\', '/');
273:
274:                    String filePath = uploadDirectory.getPath()
275:                            + File.separator;
276:                    fileName = new File(fileName).getName();
277:                    file = new File(filePath + fileName);
278:
279:                    if (!allowOverwrite && !file.createNewFile()) {
280:                        if (silentlyRename) {
281:                            int c = 0;
282:                            do {
283:                                file = new File(filePath + c++ + "_" + fileName);
284:                            } while (!file.createNewFile());
285:                        } else {
286:                            throw new MultipartException("Duplicate file '"
287:                                    + file.getName() + "' in '"
288:                                    + file.getParent() + "'");
289:                        }
290:                    }
291:
292:                    out = new FileOutputStream(file);
293:                }
294:
295:                if (hasSession) { // upload widget support
296:                    this .uploadStatus.put("finished", Boolean.FALSE);
297:                    this .uploadStatus.put("started", Boolean.TRUE);
298:                    this .uploadStatus.put("widget", headers.get("name"));
299:                    this .uploadStatus.put("filename", headers.get("filename"));
300:                }
301:
302:                int length = 0; // Track length for OversizedPart
303:                try {
304:                    int read = 0;
305:                    while (in.getState() == TokenStream.STATE_READING) { // read data
306:                        read = in.read(buf);
307:                        length += read;
308:                        out.write(buf, 0, read);
309:
310:                        if (this .hasSession) {
311:                            this .uploadStatus.put("sent", new Integer(
312:                                    ((Integer) this .uploadStatus.get("sent"))
313:                                            .intValue()
314:                                            + read));
315:                        }
316:                    }
317:                    if (this .hasSession) { // upload widget support
318:                        this .uploadStatus.put("uploadsdone",
319:                                new Integer(((Integer) this .uploadStatus
320:                                        .get("uploadsdone")).intValue() + 1));
321:                        this .uploadStatus.put("error", Boolean.FALSE);
322:                    }
323:                } catch (IOException ioe) {
324:                    // don't let incomplete file uploads pile up in the upload dir.
325:                    // this usually happens with aborted form submits containing very large files.
326:                    out.close();
327:                    out = null;
328:                    if (file != null)
329:                        file.delete();
330:                    if (this .hasSession) { // upload widget support
331:                        this .uploadStatus.put("error", Boolean.TRUE);
332:                    }
333:                    throw ioe;
334:                } finally {
335:                    if (out != null)
336:                        out.close();
337:                }
338:
339:                String name = (String) headers.get("name");
340:                if (oversized) {
341:                    this .parts.put(name, new RejectedPart(headers, length,
342:                            this .contentLength, this .maxUploadSize));
343:                } else if (file == null) {
344:                    byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
345:                    this .parts.put(name, new PartInMemory(headers,
346:                            new ByteArrayInputStream(bytes), bytes.length));
347:                } else {
348:                    this .parts.put(name, new PartOnDisk(headers, file));
349:                }
350:            }
351:
352:            /**
353:             * Parse an inline part
354:             *
355:             * @param in
356:             * @param headers
357:             *
358:             * @throws IOException
359:             */
360:            private void parseInlinePart(TokenStream in, Hashtable headers)
361:                    throws IOException {
362:
363:                // Buffer incoming bytes for proper string decoding (there can be multibyte chars)
364:                ByteArrayOutputStream bos = new ByteArrayOutputStream();
365:
366:                while (in.getState() == TokenStream.STATE_READING) {
367:                    int c = in.read();
368:                    if (c != -1)
369:                        bos.write(c);
370:                }
371:
372:                String field = (String) headers.get("name");
373:                Vector v = (Vector) this .parts.get(field);
374:
375:                if (v == null) {
376:                    v = new Vector();
377:                    this .parts.put(field, v);
378:                }
379:
380:                v.add(new String(bos.toByteArray(), this .characterEncoding));
381:            }
382:
383:            /**
384:             * Read part headers
385:             *
386:             * @param in
387:             *
388:             * @throws IOException
389:             */
390:            private Hashtable readHeaders(TokenStream in) throws IOException {
391:
392:                Hashtable headers = new Hashtable();
393:                String hdrline = readln(in);
394:
395:                while (!"".equals(hdrline)) {
396:                    StringTokenizer tokenizer = new StringTokenizer(hdrline);
397:
398:                    headers.put(tokenizer.nextToken(" :").toLowerCase(),
399:                            tokenizer.nextToken(" :;"));
400:
401:                    // The extra tokenizer.hasMoreTokens() in headers.put
402:                    // handles the filename="" case IE6 submits for an empty
403:                    // upload field.
404:                    while (tokenizer.hasMoreTokens()) {
405:                        headers.put(tokenizer.nextToken(" ;=\""), tokenizer
406:                                .hasMoreTokens() ? tokenizer.nextToken("=\"")
407:                                : "");
408:                    }
409:
410:                    hdrline = readln(in);
411:                }
412:
413:                return headers;
414:            }
415:
416:            /**
417:             * Get boundary from contentheader
418:             *
419:             * @param hdr
420:             */
421:            private String getBoundary(String hdr) {
422:
423:                int start = hdr.toLowerCase().indexOf("boundary=");
424:                if (start > -1) {
425:                    return "--" + hdr.substring(start + 9);
426:                } else {
427:                    return null;
428:                }
429:            }
430:
431:            /**
432:             * Read string until newline or end of stream
433:             *
434:             * @param in
435:             *
436:             * @throws IOException
437:             */
438:            private String readln(TokenStream in) throws IOException {
439:
440:                ByteArrayOutputStream bos = new ByteArrayOutputStream();
441:
442:                int b = in.read();
443:
444:                while ((b != -1) && (b != '\r')) {
445:                    bos.write(b);
446:                    b = in.read();
447:                }
448:
449:                if (b == '\r') {
450:                    in.read(); // read '\n'
451:                }
452:
453:                return new String(bos.toByteArray(), this.characterEncoding);
454:            }
455:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.