Source Code Cross Referenced for FileUploadBase.java in  » Net » apache-common-FileUpload » org » apache » commons » fileupload » 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 » Net » apache common FileUpload » org.apache.commons.fileupload 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:        package org.apache.commons.fileupload;
0018:
0019:        import java.io.IOException;
0020:        import java.io.InputStream;
0021:        import java.io.UnsupportedEncodingException;
0022:        import java.util.ArrayList;
0023:        import java.util.HashMap;
0024:        import java.util.List;
0025:        import java.util.Map;
0026:        import java.util.NoSuchElementException;
0027:
0028:        import javax.servlet.http.HttpServletRequest;
0029:
0030:        import org.apache.commons.fileupload.servlet.ServletFileUpload;
0031:        import org.apache.commons.fileupload.servlet.ServletRequestContext;
0032:        import org.apache.commons.fileupload.util.Closeable;
0033:        import org.apache.commons.fileupload.util.LimitedInputStream;
0034:        import org.apache.commons.fileupload.util.Streams;
0035:
0036:        /**
0037:         * <p>High level API for processing file uploads.</p>
0038:         *
0039:         * <p>This class handles multiple files per single HTML widget, sent using
0040:         * <code>multipart/mixed</code> encoding type, as specified by
0041:         * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>.  Use {@link
0042:         * #parseRequest(HttpServletRequest)} to acquire a list of {@link
0043:         * org.apache.commons.fileupload.FileItem}s associated with a given HTML
0044:         * widget.</p>
0045:         *
0046:         * <p>How the data for individual parts is stored is determined by the factory
0047:         * used to create them; a given part may be in memory, on disk, or somewhere
0048:         * else.</p>
0049:         *
0050:         * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
0051:         * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
0052:         * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
0053:         * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
0054:         * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
0055:         * @author Sean C. Sullivan
0056:         *
0057:         * @version $Id: FileUploadBase.java 502350 2007-02-01 20:42:48Z jochen $
0058:         */
0059:        public abstract class FileUploadBase {
0060:
0061:            // ---------------------------------------------------------- Class methods
0062:
0063:            /**
0064:             * <p>Utility method that determines whether the request contains multipart
0065:             * content.</p>
0066:             *
0067:             * <p><strong>NOTE:</strong>This method will be moved to the
0068:             * <code>ServletFileUpload</code> class after the FileUpload 1.1 release.
0069:             * Unfortunately, since this method is static, it is not possible to
0070:             * provide its replacement until this method is removed.</p>
0071:             *
0072:             * @param ctx The request context to be evaluated. Must be non-null.
0073:             *
0074:             * @return <code>true</code> if the request is multipart;
0075:             *         <code>false</code> otherwise.
0076:             */
0077:            public static final boolean isMultipartContent(RequestContext ctx) {
0078:                String contentType = ctx.getContentType();
0079:                if (contentType == null) {
0080:                    return false;
0081:                }
0082:                if (contentType.toLowerCase().startsWith(MULTIPART)) {
0083:                    return true;
0084:                }
0085:                return false;
0086:            }
0087:
0088:            /**
0089:             * Utility method that determines whether the request contains multipart
0090:             * content.
0091:             *
0092:             * @param req The servlet request to be evaluated. Must be non-null.
0093:             *
0094:             * @return <code>true</code> if the request is multipart;
0095:             *         <code>false</code> otherwise.
0096:             *
0097:             * @deprecated Use the method on <code>ServletFileUpload</code> instead.
0098:             */
0099:            public static boolean isMultipartContent(HttpServletRequest req) {
0100:                return ServletFileUpload.isMultipartContent(req);
0101:            }
0102:
0103:            // ----------------------------------------------------- Manifest constants
0104:
0105:            /**
0106:             * HTTP content type header name.
0107:             */
0108:            public static final String CONTENT_TYPE = "Content-type";
0109:
0110:            /**
0111:             * HTTP content disposition header name.
0112:             */
0113:            public static final String CONTENT_DISPOSITION = "Content-disposition";
0114:
0115:            /**
0116:             * Content-disposition value for form data.
0117:             */
0118:            public static final String FORM_DATA = "form-data";
0119:
0120:            /**
0121:             * Content-disposition value for file attachment.
0122:             */
0123:            public static final String ATTACHMENT = "attachment";
0124:
0125:            /**
0126:             * Part of HTTP content type header.
0127:             */
0128:            public static final String MULTIPART = "multipart/";
0129:
0130:            /**
0131:             * HTTP content type header for multipart forms.
0132:             */
0133:            public static final String MULTIPART_FORM_DATA = "multipart/form-data";
0134:
0135:            /**
0136:             * HTTP content type header for multiple uploads.
0137:             */
0138:            public static final String MULTIPART_MIXED = "multipart/mixed";
0139:
0140:            /**
0141:             * The maximum length of a single header line that will be parsed
0142:             * (1024 bytes).
0143:             * @deprecated This constant is no longer used. As of commons-fileupload
0144:             *   1.2, the only applicable limit is the total size of a parts headers,
0145:             *   {@link MultipartStream#HEADER_PART_SIZE_MAX}.
0146:             */
0147:            public static final int MAX_HEADER_SIZE = 1024;
0148:
0149:            // ----------------------------------------------------------- Data members
0150:
0151:            /**
0152:             * The maximum size permitted for the complete request, as opposed to
0153:             * {@link #fileSizeMax}. A value of -1 indicates no maximum.
0154:             */
0155:            private long sizeMax = -1;
0156:
0157:            /**
0158:             * The maximum size permitted for a single uploaded file, as opposed
0159:             * to {@link #sizeMax}. A value of -1 indicates no maximum.
0160:             */
0161:            private long fileSizeMax = -1;
0162:
0163:            /**
0164:             * The content encoding to use when reading part headers.
0165:             */
0166:            private String headerEncoding;
0167:
0168:            /**
0169:             * The progress listener.
0170:             */
0171:            private ProgressListener listener;
0172:
0173:            // ----------------------------------------------------- Property accessors
0174:
0175:            /**
0176:             * Returns the factory class used when creating file items.
0177:             *
0178:             * @return The factory class for new file items.
0179:             */
0180:            public abstract FileItemFactory getFileItemFactory();
0181:
0182:            /**
0183:             * Sets the factory class to use when creating file items.
0184:             *
0185:             * @param factory The factory class for new file items.
0186:             */
0187:            public abstract void setFileItemFactory(FileItemFactory factory);
0188:
0189:            /**
0190:             * Returns the maximum allowed size of a complete request, as opposed
0191:             * to {@link #getFileSizeMax()}.
0192:             *
0193:             * @return The maximum allowed size, in bytes. The default value of
0194:             *   -1 indicates, that there is no limit.
0195:             *
0196:             * @see #setSizeMax(long)
0197:             *
0198:             */
0199:            public long getSizeMax() {
0200:                return sizeMax;
0201:            }
0202:
0203:            /**
0204:             * Sets the maximum allowed size of a complete request, as opposed
0205:             * to {@link #setFileSizeMax(long)}.
0206:             *
0207:             * @param sizeMax The maximum allowed size, in bytes. The default value of
0208:             *   -1 indicates, that there is no limit.
0209:             *
0210:             * @see #getSizeMax()
0211:             *
0212:             */
0213:            public void setSizeMax(long sizeMax) {
0214:                this .sizeMax = sizeMax;
0215:            }
0216:
0217:            /**
0218:             * Returns the maximum allowed size of a single uploaded file,
0219:             * as opposed to {@link #getSizeMax()}.
0220:             *
0221:             * @see #setFileSizeMax(long)
0222:             * @return Maximum size of a single uploaded file.
0223:             */
0224:            public long getFileSizeMax() {
0225:                return fileSizeMax;
0226:            }
0227:
0228:            /**
0229:             * Sets the maximum allowed size of a single uploaded file,
0230:             * as opposed to {@link #getSizeMax()}.
0231:             *
0232:             * @see #getFileSizeMax()
0233:             * @param fileSizeMax Maximum size of a single uploaded file.
0234:             */
0235:            public void setFileSizeMax(long fileSizeMax) {
0236:                this .fileSizeMax = fileSizeMax;
0237:            }
0238:
0239:            /**
0240:             * Retrieves the character encoding used when reading the headers of an
0241:             * individual part. When not specified, or <code>null</code>, the request
0242:             * encoding is used. If that is also not specified, or <code>null</code>,
0243:             * the platform default encoding is used.
0244:             *
0245:             * @return The encoding used to read part headers.
0246:             */
0247:            public String getHeaderEncoding() {
0248:                return headerEncoding;
0249:            }
0250:
0251:            /**
0252:             * Specifies the character encoding to be used when reading the headers of
0253:             * individual part. When not specified, or <code>null</code>, the request
0254:             * encoding is used. If that is also not specified, or <code>null</code>,
0255:             * the platform default encoding is used.
0256:             *
0257:             * @param encoding The encoding used to read part headers.
0258:             */
0259:            public void setHeaderEncoding(String encoding) {
0260:                headerEncoding = encoding;
0261:            }
0262:
0263:            // --------------------------------------------------------- Public methods
0264:
0265:            /**
0266:             * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
0267:             * compliant <code>multipart/form-data</code> stream.
0268:             *
0269:             * @param req The servlet request to be parsed.
0270:             *
0271:             * @return A list of <code>FileItem</code> instances parsed from the
0272:             *         request, in the order that they were transmitted.
0273:             *
0274:             * @throws FileUploadException if there are problems reading/parsing
0275:             *                             the request or storing files.
0276:             *
0277:             * @deprecated Use the method in <code>ServletFileUpload</code> instead.
0278:             */
0279:            public List /* FileItem */parseRequest(HttpServletRequest req)
0280:                    throws FileUploadException {
0281:                return parseRequest(new ServletRequestContext(req));
0282:            }
0283:
0284:            /**
0285:             * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
0286:             * compliant <code>multipart/form-data</code> stream.
0287:             *
0288:             * @param ctx The context for the request to be parsed.
0289:             *
0290:             * @return An iterator to instances of <code>FileItemStream</code>
0291:             *         parsed from the request, in the order that they were
0292:             *         transmitted.
0293:             *
0294:             * @throws FileUploadException if there are problems reading/parsing
0295:             *                             the request or storing files.
0296:             * @throws IOException An I/O error occurred. This may be a network
0297:             *   error while communicating with the client or a problem while
0298:             *   storing the uploaded content.
0299:             */
0300:            public FileItemIterator getItemIterator(RequestContext ctx)
0301:                    throws FileUploadException, IOException {
0302:                return new FileItemIteratorImpl(ctx);
0303:            }
0304:
0305:            /**
0306:             * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
0307:             * compliant <code>multipart/form-data</code> stream.
0308:             *
0309:             * @param ctx The context for the request to be parsed.
0310:             *
0311:             * @return A list of <code>FileItem</code> instances parsed from the
0312:             *         request, in the order that they were transmitted.
0313:             *
0314:             * @throws FileUploadException if there are problems reading/parsing
0315:             *                             the request or storing files.
0316:             */
0317:            public List /* FileItem */parseRequest(RequestContext ctx)
0318:                    throws FileUploadException {
0319:                try {
0320:                    FileItemIterator iter = getItemIterator(ctx);
0321:                    List items = new ArrayList();
0322:                    FileItemFactory fac = getFileItemFactory();
0323:                    if (fac == null) {
0324:                        throw new NullPointerException(
0325:                                "No FileItemFactory has been set.");
0326:                    }
0327:                    while (iter.hasNext()) {
0328:                        FileItemStream item = iter.next();
0329:                        FileItem fileItem = fac.createItem(item.getFieldName(),
0330:                                item.getContentType(), item.isFormField(), item
0331:                                        .getName());
0332:                        try {
0333:                            Streams.copy(item.openStream(), fileItem
0334:                                    .getOutputStream(), true);
0335:                        } catch (FileUploadIOException e) {
0336:                            throw (FileUploadException) e.getCause();
0337:                        } catch (IOException e) {
0338:                            throw new IOFileUploadException("Processing of "
0339:                                    + MULTIPART_FORM_DATA + " request failed. "
0340:                                    + e.getMessage(), e);
0341:                        }
0342:                        items.add(fileItem);
0343:                    }
0344:                    return items;
0345:                } catch (FileUploadIOException e) {
0346:                    throw (FileUploadException) e.getCause();
0347:                } catch (IOException e) {
0348:                    throw new FileUploadException(e.getMessage(), e);
0349:                }
0350:            }
0351:
0352:            // ------------------------------------------------------ Protected methods
0353:
0354:            /**
0355:             * Retrieves the boundary from the <code>Content-type</code> header.
0356:             *
0357:             * @param contentType The value of the content type header from which to
0358:             *                    extract the boundary value.
0359:             *
0360:             * @return The boundary, as a byte array.
0361:             */
0362:            protected byte[] getBoundary(String contentType) {
0363:                ParameterParser parser = new ParameterParser();
0364:                parser.setLowerCaseNames(true);
0365:                // Parameter parser can handle null input
0366:                Map params = parser.parse(contentType, ';');
0367:                String boundaryStr = (String) params.get("boundary");
0368:
0369:                if (boundaryStr == null) {
0370:                    return null;
0371:                }
0372:                byte[] boundary;
0373:                try {
0374:                    boundary = boundaryStr.getBytes("ISO-8859-1");
0375:                } catch (UnsupportedEncodingException e) {
0376:                    boundary = boundaryStr.getBytes();
0377:                }
0378:                return boundary;
0379:            }
0380:
0381:            /**
0382:             * Retrieves the file name from the <code>Content-disposition</code>
0383:             * header.
0384:             *
0385:             * @param headers A <code>Map</code> containing the HTTP request headers.
0386:             *
0387:             * @return The file name for the current <code>encapsulation</code>.
0388:             */
0389:            protected String getFileName(Map /* String, String */headers) {
0390:                String fileName = null;
0391:                String cd = getHeader(headers, CONTENT_DISPOSITION);
0392:                if (cd != null) {
0393:                    String cdl = cd.toLowerCase();
0394:                    if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) {
0395:                        ParameterParser parser = new ParameterParser();
0396:                        parser.setLowerCaseNames(true);
0397:                        // Parameter parser can handle null input
0398:                        Map params = parser.parse(cd, ';');
0399:                        if (params.containsKey("filename")) {
0400:                            fileName = (String) params.get("filename");
0401:                            if (fileName != null) {
0402:                                fileName = fileName.trim();
0403:                            } else {
0404:                                // Even if there is no value, the parameter is present,
0405:                                // so we return an empty file name rather than no file
0406:                                // name.
0407:                                fileName = "";
0408:                            }
0409:                        }
0410:                    }
0411:                }
0412:                return fileName;
0413:            }
0414:
0415:            /**
0416:             * Retrieves the field name from the <code>Content-disposition</code>
0417:             * header.
0418:             *
0419:             * @param headers A <code>Map</code> containing the HTTP request headers.
0420:             *
0421:             * @return The field name for the current <code>encapsulation</code>.
0422:             */
0423:            protected String getFieldName(Map /* String, String */headers) {
0424:                String fieldName = null;
0425:                String cd = getHeader(headers, CONTENT_DISPOSITION);
0426:                if (cd != null && cd.toLowerCase().startsWith(FORM_DATA)) {
0427:
0428:                    ParameterParser parser = new ParameterParser();
0429:                    parser.setLowerCaseNames(true);
0430:                    // Parameter parser can handle null input
0431:                    Map params = parser.parse(cd, ';');
0432:                    fieldName = (String) params.get("name");
0433:                    if (fieldName != null) {
0434:                        fieldName = fieldName.trim();
0435:                    }
0436:                }
0437:                return fieldName;
0438:            }
0439:
0440:            /**
0441:             * Creates a new {@link FileItem} instance.
0442:             *
0443:             * @param headers       A <code>Map</code> containing the HTTP request
0444:             *                      headers.
0445:             * @param isFormField   Whether or not this item is a form field, as
0446:             *                      opposed to a file.
0447:             *
0448:             * @return A newly created <code>FileItem</code> instance.
0449:             *
0450:             * @throws FileUploadException if an error occurs.
0451:             * @deprecated This method is no longer used in favour of
0452:             *   internally created instances of {@link FileItem}.
0453:             */
0454:            protected FileItem createItem(Map /* String, String */headers,
0455:                    boolean isFormField) throws FileUploadException {
0456:                return getFileItemFactory().createItem(getFieldName(headers),
0457:                        getHeader(headers, CONTENT_TYPE), isFormField,
0458:                        getFileName(headers));
0459:            }
0460:
0461:            /**
0462:             * <p> Parses the <code>header-part</code> and returns as key/value
0463:             * pairs.
0464:             *
0465:             * <p> If there are multiple headers of the same names, the name
0466:             * will map to a comma-separated list containing the values.
0467:             *
0468:             * @param headerPart The <code>header-part</code> of the current
0469:             *                   <code>encapsulation</code>.
0470:             *
0471:             * @return A <code>Map</code> containing the parsed HTTP request headers.
0472:             */
0473:            protected Map /* String, String */parseHeaders(String headerPart) {
0474:                final int len = headerPart.length();
0475:                Map headers = new HashMap();
0476:                int start = 0;
0477:                for (;;) {
0478:                    int end = parseEndOfLine(headerPart, start);
0479:                    if (start == end) {
0480:                        break;
0481:                    }
0482:                    String header = headerPart.substring(start, end);
0483:                    start = end + 2;
0484:                    while (start < len) {
0485:                        int nonWs = start;
0486:                        while (nonWs < len) {
0487:                            char c = headerPart.charAt(nonWs);
0488:                            if (c != ' ' && c != '\t') {
0489:                                break;
0490:                            }
0491:                            ++nonWs;
0492:                        }
0493:                        if (nonWs == start) {
0494:                            break;
0495:                        }
0496:                        // Continuation line found
0497:                        end = parseEndOfLine(headerPart, nonWs);
0498:                        header += " " + headerPart.substring(nonWs, end);
0499:                        start = end + 2;
0500:                    }
0501:                    parseHeaderLine(headers, header);
0502:                }
0503:                return headers;
0504:            }
0505:
0506:            /**
0507:             * Skips bytes until the end of the current line.
0508:             * @param headerPart The headers, which are being parsed.
0509:             * @param end Index of the last byte, which has yet been
0510:             *   processed.
0511:             * @return Index of the \r\n sequence, which indicates
0512:             *   end of line.
0513:             */
0514:            private int parseEndOfLine(String headerPart, int end) {
0515:                int index = end;
0516:                for (;;) {
0517:                    int offset = headerPart.indexOf('\r', index);
0518:                    if (offset == -1 || offset + 1 >= headerPart.length()) {
0519:                        throw new IllegalStateException(
0520:                                "Expected headers to be terminated by an empty line.");
0521:                    }
0522:                    if (headerPart.charAt(offset + 1) == '\n') {
0523:                        return offset;
0524:                    }
0525:                    index = offset + 1;
0526:                }
0527:            }
0528:
0529:            /**
0530:             * Reads the next header line.
0531:             * @param headers String with all headers.
0532:             * @param header Map where to store the current header.
0533:             */
0534:            private void parseHeaderLine(Map headers, String header) {
0535:                final int colonOffset = header.indexOf(':');
0536:                if (colonOffset == -1) {
0537:                    // This header line is malformed, skip it.
0538:                    return;
0539:                }
0540:                String headerName = header.substring(0, colonOffset).trim()
0541:                        .toLowerCase();
0542:                String headerValue = header.substring(header.indexOf(':') + 1)
0543:                        .trim();
0544:                if (getHeader(headers, headerName) != null) {
0545:                    // More that one heder of that name exists,
0546:                    // append to the list.
0547:                    headers.put(headerName, getHeader(headers, headerName)
0548:                            + ',' + headerValue);
0549:                } else {
0550:                    headers.put(headerName, headerValue);
0551:                }
0552:            }
0553:
0554:            /**
0555:             * Returns the header with the specified name from the supplied map. The
0556:             * header lookup is case-insensitive.
0557:             *
0558:             * @param headers A <code>Map</code> containing the HTTP request headers.
0559:             * @param name    The name of the header to return.
0560:             *
0561:             * @return The value of specified header, or a comma-separated list if
0562:             *         there were multiple headers of that name.
0563:             */
0564:            protected final String getHeader(Map /* String, String */headers,
0565:                    String name) {
0566:                return (String) headers.get(name.toLowerCase());
0567:            }
0568:
0569:            /**
0570:             * The iterator, which is returned by
0571:             * {@link FileUploadBase#getItemIterator(RequestContext)}.
0572:             */
0573:            private class FileItemIteratorImpl implements  FileItemIterator {
0574:                /**
0575:                 * Default implementation of {@link FileItemStream}.
0576:                 */
0577:                private class FileItemStreamImpl implements  FileItemStream {
0578:                    /** The file items content type.
0579:                     */
0580:                    private final String contentType;
0581:                    /** The file items field name.
0582:                     */
0583:                    private final String fieldName;
0584:                    /** The file items file name.
0585:                     */
0586:                    private final String name;
0587:                    /** Whether the file item is a form field.
0588:                     */
0589:                    private final boolean formField;
0590:                    /** The file items input stream.
0591:                     */
0592:                    private final InputStream stream;
0593:                    /** Whether the file item was already opened.
0594:                     */
0595:                    private boolean opened;
0596:
0597:                    /**
0598:                     * CReates a new instance.
0599:                     * @param pName The items file name, or null.
0600:                     * @param pFieldName The items field name.
0601:                     * @param pContentType The items content type, or null.
0602:                     * @param pFormField Whether the item is a form field.
0603:                     */
0604:                    FileItemStreamImpl(String pName, String pFieldName,
0605:                            String pContentType, boolean pFormField) {
0606:                        name = pName;
0607:                        fieldName = pFieldName;
0608:                        contentType = pContentType;
0609:                        formField = pFormField;
0610:                        InputStream istream = multi.newInputStream();
0611:                        if (fileSizeMax != -1) {
0612:                            istream = new LimitedInputStream(istream,
0613:                                    fileSizeMax) {
0614:                                protected void raiseError(long pSizeMax,
0615:                                        long pCount) throws IOException {
0616:                                    FileUploadException e = new FileSizeLimitExceededException(
0617:                                            "The field "
0618:                                                    + fieldName
0619:                                                    + " exceeds its maximum permitted "
0620:                                                    + " size of " + pSizeMax
0621:                                                    + " characters.", pCount,
0622:                                            pSizeMax);
0623:                                    throw new FileUploadIOException(e);
0624:                                }
0625:                            };
0626:                        }
0627:                        stream = istream;
0628:                    }
0629:
0630:                    /**
0631:                     * Returns the items content type, or null.
0632:                     * @return Content type, if known, or null.
0633:                     */
0634:                    public String getContentType() {
0635:                        return contentType;
0636:                    }
0637:
0638:                    /**
0639:                     * Returns the items field name.
0640:                     * @return Field name.
0641:                     */
0642:                    public String getFieldName() {
0643:                        return fieldName;
0644:                    }
0645:
0646:                    /**
0647:                     * Returns the items file name.
0648:                     * @return File name, if known, or null.
0649:                     */
0650:                    public String getName() {
0651:                        return name;
0652:                    }
0653:
0654:                    /**
0655:                     * Returns, whether this is a form field.
0656:                     * @return True, if the item is a form field,
0657:                     *   otherwise false.
0658:                     */
0659:                    public boolean isFormField() {
0660:                        return formField;
0661:                    }
0662:
0663:                    /**
0664:                     * Returns an input stream, which may be used to
0665:                     * read the items contents.
0666:                     * @return Opened input stream.
0667:                     * @throws IOException An I/O error occurred.
0668:                     */
0669:                    public InputStream openStream() throws IOException {
0670:                        if (opened) {
0671:                            throw new IllegalStateException(
0672:                                    "The stream was already opened.");
0673:                        }
0674:                        if (((Closeable) stream).isClosed()) {
0675:                            throw new FileItemStream.ItemSkippedException();
0676:                        }
0677:                        return stream;
0678:                    }
0679:
0680:                    /**
0681:                     * Closes the file item.
0682:                     * @throws IOException An I/O error occurred.
0683:                     */
0684:                    void close() throws IOException {
0685:                        stream.close();
0686:                    }
0687:                }
0688:
0689:                /**
0690:                 * The multi part stream to process.
0691:                 */
0692:                private final MultipartStream multi;
0693:                /**
0694:                 * The notifier, which used for triggering the
0695:                 * {@link ProgressListener}.
0696:                 */
0697:                private final MultipartStream.ProgressNotifier notifier;
0698:                /**
0699:                 * The boundary, which separates the various parts.
0700:                 */
0701:                private final byte[] boundary;
0702:                /**
0703:                 * The item, which we currently process.
0704:                 */
0705:                private FileItemStreamImpl currentItem;
0706:                /**
0707:                 * The current items field name.
0708:                 */
0709:                private String currentFieldName;
0710:                /**
0711:                 * Whether we are currently skipping the preamble.
0712:                 */
0713:                private boolean skipPreamble;
0714:                /**
0715:                 * Whether the current item may still be read.
0716:                 */
0717:                private boolean itemValid;
0718:                /**
0719:                 * Whether we have seen the end of the file.
0720:                 */
0721:                private boolean eof;
0722:
0723:                /**
0724:                 * Creates a new instance.
0725:                 * @param ctx The request context.
0726:                 * @throws FileUploadException An error occurred while
0727:                 *   parsing the request.
0728:                 * @throws IOException An I/O error occurred.
0729:                 */
0730:                FileItemIteratorImpl(RequestContext ctx)
0731:                        throws FileUploadException, IOException {
0732:                    if (ctx == null) {
0733:                        throw new NullPointerException("ctx parameter");
0734:                    }
0735:
0736:                    String contentType = ctx.getContentType();
0737:                    if ((null == contentType)
0738:                            || (!contentType.toLowerCase()
0739:                                    .startsWith(MULTIPART))) {
0740:                        throw new InvalidContentTypeException(
0741:                                "the request doesn't contain a "
0742:                                        + MULTIPART_FORM_DATA + " or "
0743:                                        + MULTIPART_MIXED
0744:                                        + " stream, content type header is "
0745:                                        + contentType);
0746:                    }
0747:
0748:                    InputStream input = ctx.getInputStream();
0749:
0750:                    if (sizeMax >= 0) {
0751:                        int requestSize = ctx.getContentLength();
0752:                        if (requestSize == -1) {
0753:                            input = new LimitedInputStream(input, sizeMax) {
0754:                                protected void raiseError(long pSizeMax,
0755:                                        long pCount) throws IOException {
0756:                                    FileUploadException ex = new SizeLimitExceededException(
0757:                                            "the request was rejected because"
0758:                                                    + " its size ("
0759:                                                    + pCount
0760:                                                    + ") exceeds the configured maximum"
0761:                                                    + " (" + pSizeMax + ")",
0762:                                            pCount, pSizeMax);
0763:                                    throw new FileUploadIOException(ex);
0764:                                }
0765:                            };
0766:                        } else {
0767:                            if (sizeMax >= 0 && requestSize > sizeMax) {
0768:                                throw new SizeLimitExceededException(
0769:                                        "the request was rejected because its size ("
0770:                                                + requestSize
0771:                                                + ") exceeds the configured maximum ("
0772:                                                + sizeMax + ")", requestSize,
0773:                                        sizeMax);
0774:                            }
0775:                        }
0776:                    }
0777:
0778:                    String charEncoding = headerEncoding;
0779:                    if (charEncoding == null) {
0780:                        charEncoding = ctx.getCharacterEncoding();
0781:                    }
0782:
0783:                    boundary = getBoundary(contentType);
0784:                    if (boundary == null) {
0785:                        throw new FileUploadException(
0786:                                "the request was rejected because "
0787:                                        + "no multipart boundary was found");
0788:                    }
0789:
0790:                    notifier = new MultipartStream.ProgressNotifier(listener,
0791:                            ctx.getContentLength());
0792:                    multi = new MultipartStream(input, boundary, notifier);
0793:                    multi.setHeaderEncoding(charEncoding);
0794:
0795:                    skipPreamble = true;
0796:                    findNextItem();
0797:                }
0798:
0799:                /**
0800:                 * Called for finding the nex item, if any.
0801:                 * @return True, if an next item was found, otherwise false.
0802:                 * @throws IOException An I/O error occurred.
0803:                 */
0804:                private boolean findNextItem() throws IOException {
0805:                    if (eof) {
0806:                        return false;
0807:                    }
0808:                    if (currentItem != null) {
0809:                        currentItem.close();
0810:                        currentItem = null;
0811:                    }
0812:                    for (;;) {
0813:                        boolean nextPart;
0814:                        if (skipPreamble) {
0815:                            nextPart = multi.skipPreamble();
0816:                        } else {
0817:                            nextPart = multi.readBoundary();
0818:                        }
0819:                        if (!nextPart) {
0820:                            if (currentFieldName == null) {
0821:                                // Outer multipart terminated -> No more data
0822:                                eof = true;
0823:                                return false;
0824:                            }
0825:                            // Inner multipart terminated -> Return to parsing the outer
0826:                            multi.setBoundary(boundary);
0827:                            currentFieldName = null;
0828:                            continue;
0829:                        }
0830:                        Map headers = parseHeaders(multi.readHeaders());
0831:                        if (currentFieldName == null) {
0832:                            // We're parsing the outer multipart
0833:                            String fieldName = getFieldName(headers);
0834:                            if (fieldName != null) {
0835:                                String subContentType = getHeader(headers,
0836:                                        CONTENT_TYPE);
0837:                                if (subContentType != null
0838:                                        && subContentType.toLowerCase()
0839:                                                .startsWith(MULTIPART_MIXED)) {
0840:                                    currentFieldName = fieldName;
0841:                                    // Multiple files associated with this field name
0842:                                    byte[] subBoundary = getBoundary(subContentType);
0843:                                    multi.setBoundary(subBoundary);
0844:                                    skipPreamble = true;
0845:                                    continue;
0846:                                }
0847:                                String fileName = getFileName(headers);
0848:                                currentItem = new FileItemStreamImpl(fileName,
0849:                                        fieldName, getHeader(headers,
0850:                                                CONTENT_TYPE), fileName == null);
0851:                                notifier.noteItem();
0852:                                itemValid = true;
0853:                                return true;
0854:                            }
0855:                        } else {
0856:                            String fileName = getFileName(headers);
0857:                            if (fileName != null) {
0858:                                currentItem = new FileItemStreamImpl(fileName,
0859:                                        currentFieldName, getHeader(headers,
0860:                                                CONTENT_TYPE), false);
0861:                                notifier.noteItem();
0862:                                itemValid = true;
0863:                                return true;
0864:                            }
0865:                        }
0866:                        multi.discardBodyData();
0867:                    }
0868:                }
0869:
0870:                /**
0871:                 * Returns, whether another instance of {@link FileItemStream}
0872:                 * is available.
0873:                 * @throws FileUploadException Parsing or processing the
0874:                 *   file item failed.
0875:                 * @throws IOException Reading the file item failed.
0876:                 * @return True, if one or more additional file items
0877:                 *   are available, otherwise false.
0878:                 */
0879:                public boolean hasNext() throws FileUploadException,
0880:                        IOException {
0881:                    if (eof) {
0882:                        return false;
0883:                    }
0884:                    if (itemValid) {
0885:                        return true;
0886:                    }
0887:                    return findNextItem();
0888:                }
0889:
0890:                /**
0891:                 * Returns the next available {@link FileItemStream}.
0892:                 * @throws java.util.NoSuchElementException No more items are
0893:                 *   available. Use {@link #hasNext()} to prevent this exception.
0894:                 * @throws FileUploadException Parsing or processing the
0895:                 *   file item failed.
0896:                 * @throws IOException Reading the file item failed.
0897:                 * @return FileItemStream instance, which provides
0898:                 *   access to the next file item.
0899:                 */
0900:                public FileItemStream next() throws FileUploadException,
0901:                        IOException {
0902:                    if (eof || (!itemValid && !hasNext())) {
0903:                        throw new NoSuchElementException();
0904:                    }
0905:                    itemValid = false;
0906:                    return currentItem;
0907:                }
0908:            }
0909:
0910:            /**
0911:             * This exception is thrown for hiding an inner
0912:             * {@link FileUploadException} in an {@link IOException}.
0913:             */
0914:            public static class FileUploadIOException extends IOException {
0915:                /** The exceptions UID, for serializing an instance.
0916:                 */
0917:                private static final long serialVersionUID = -7047616958165584154L;
0918:                /** The exceptions cause; we overwrite the parent
0919:                 * classes field, which is available since Java
0920:                 * 1.4 only.
0921:                 */
0922:                private final FileUploadException cause;
0923:
0924:                /**
0925:                 * Creates a <code>FileUploadIOException</code> with the
0926:                 * given cause.
0927:                 * @param pCause The exceptions cause, if any, or null.
0928:                 */
0929:                public FileUploadIOException(FileUploadException pCause) {
0930:                    // We're not doing super(pCause) cause of 1.3 compatibility.
0931:                    cause = pCause;
0932:                }
0933:
0934:                /**
0935:                 * Returns the exceptions cause.
0936:                 * @return The exceptions cause, if any, or null.
0937:                 */
0938:                public Throwable getCause() {
0939:                    return cause;
0940:                }
0941:            }
0942:
0943:            /**
0944:             * Thrown to indicate that the request is not a multipart request.
0945:             */
0946:            public static class InvalidContentTypeException extends
0947:                    FileUploadException {
0948:                /** The exceptions UID, for serializing an instance.
0949:                 */
0950:                private static final long serialVersionUID = -9073026332015646668L;
0951:
0952:                /**
0953:                 * Constructs a <code>InvalidContentTypeException</code> with no
0954:                 * detail message.
0955:                 */
0956:                public InvalidContentTypeException() {
0957:                    // Nothing to do.
0958:                }
0959:
0960:                /**
0961:                 * Constructs an <code>InvalidContentTypeException</code> with
0962:                 * the specified detail message.
0963:                 *
0964:                 * @param message The detail message.
0965:                 */
0966:                public InvalidContentTypeException(String message) {
0967:                    super (message);
0968:                }
0969:            }
0970:
0971:            /**
0972:             * Thrown to indicate an IOException.
0973:             */
0974:            public static class IOFileUploadException extends
0975:                    FileUploadException {
0976:                /** The exceptions UID, for serializing an instance.
0977:                 */
0978:                private static final long serialVersionUID = 1749796615868477269L;
0979:                /** The exceptions cause; we overwrite the parent
0980:                 * classes field, which is available since Java
0981:                 * 1.4 only.
0982:                 */
0983:                private final IOException cause;
0984:
0985:                /**
0986:                 * Creates a new instance with the given cause.
0987:                 * @param pMsg The detail message.
0988:                 * @param pException The exceptions cause.
0989:                 */
0990:                public IOFileUploadException(String pMsg, IOException pException) {
0991:                    super (pMsg);
0992:                    cause = pException;
0993:                }
0994:
0995:                /**
0996:                 * Returns the exceptions cause.
0997:                 * @return The exceptions cause, if any, or null.
0998:                 */
0999:                public Throwable getCause() {
1000:                    return cause;
1001:                }
1002:            }
1003:
1004:            /** This exception is thrown, if a requests permitted size
1005:             * is exceeded.
1006:             */
1007:            protected abstract static class SizeException extends
1008:                    FileUploadException {
1009:                /**
1010:                 * The actual size of the request.
1011:                 */
1012:                private final long actual;
1013:
1014:                /**
1015:                 * The maximum permitted size of the request.
1016:                 */
1017:                private final long permitted;
1018:
1019:                /**
1020:                 * Creates a new instance.
1021:                 * @param message The detail message.
1022:                 * @param actual The actual number of bytes in the request.
1023:                 * @param permitted The requests size limit, in bytes.
1024:                 */
1025:                protected SizeException(String message, long actual,
1026:                        long permitted) {
1027:                    super (message);
1028:                    this .actual = actual;
1029:                    this .permitted = permitted;
1030:                }
1031:
1032:                /**
1033:                 * Retrieves the actual size of the request.
1034:                 *
1035:                 * @return The actual size of the request.
1036:                 */
1037:                public long getActualSize() {
1038:                    return actual;
1039:                }
1040:
1041:                /**
1042:                 * Retrieves the permitted size of the request.
1043:                 *
1044:                 * @return The permitted size of the request.
1045:                 */
1046:                public long getPermittedSize() {
1047:                    return permitted;
1048:                }
1049:            }
1050:
1051:            /**
1052:             * Thrown to indicate that the request size is not specified. In other
1053:             * words, it is thrown, if the content-length header is missing or
1054:             * contains the value -1.
1055:             * @deprecated As of commons-fileupload 1.2, the presence of a
1056:             *   content-length header is no longer required.
1057:             */
1058:            public static class UnknownSizeException extends
1059:                    FileUploadException {
1060:                /** The exceptions UID, for serializing an instance.
1061:                 */
1062:                private static final long serialVersionUID = 7062279004812015273L;
1063:
1064:                /**
1065:                 * Constructs a <code>UnknownSizeException</code> with no
1066:                 * detail message.
1067:                 */
1068:                public UnknownSizeException() {
1069:                    super ();
1070:                }
1071:
1072:                /**
1073:                 * Constructs an <code>UnknownSizeException</code> with
1074:                 * the specified detail message.
1075:                 *
1076:                 * @param message The detail message.
1077:                 */
1078:                public UnknownSizeException(String message) {
1079:                    super (message);
1080:                }
1081:            }
1082:
1083:            /**
1084:             * Thrown to indicate that the request size exceeds the configured maximum.
1085:             */
1086:            public static class SizeLimitExceededException extends
1087:                    SizeException {
1088:                /** The exceptions UID, for serializing an instance.
1089:                 */
1090:                private static final long serialVersionUID = -2474893167098052828L;
1091:
1092:                /**
1093:                 * @deprecated Replaced by
1094:                 * {@link #SizeLimitExceededException(String, long, long)}
1095:                 */
1096:                public SizeLimitExceededException() {
1097:                    this (null, 0, 0);
1098:                }
1099:
1100:                /**
1101:                 * @deprecated Replaced by
1102:                 * {@link #SizeLimitExceededException(String, long, long)}
1103:                 * @param message The exceptions detail message.
1104:                 */
1105:                public SizeLimitExceededException(String message) {
1106:                    this (message, 0, 0);
1107:                }
1108:
1109:                /**
1110:                 * Constructs a <code>SizeExceededException</code> with
1111:                 * the specified detail message, and actual and permitted sizes.
1112:                 *
1113:                 * @param message   The detail message.
1114:                 * @param actual    The actual request size.
1115:                 * @param permitted The maximum permitted request size.
1116:                 */
1117:                public SizeLimitExceededException(String message, long actual,
1118:                        long permitted) {
1119:                    super (message, actual, permitted);
1120:                }
1121:            }
1122:
1123:            /**
1124:             * Thrown to indicate that A files size exceeds the configured maximum.
1125:             */
1126:            public static class FileSizeLimitExceededException extends
1127:                    SizeException {
1128:                /** The exceptions UID, for serializing an instance.
1129:                 */
1130:                private static final long serialVersionUID = 8150776562029630058L;
1131:
1132:                /**
1133:                 * Constructs a <code>SizeExceededException</code> with
1134:                 * the specified detail message, and actual and permitted sizes.
1135:                 *
1136:                 * @param message   The detail message.
1137:                 * @param actual    The actual request size.
1138:                 * @param permitted The maximum permitted request size.
1139:                 */
1140:                public FileSizeLimitExceededException(String message,
1141:                        long actual, long permitted) {
1142:                    super (message, actual, permitted);
1143:                }
1144:            }
1145:
1146:            /**
1147:             * Returns the progress listener.
1148:             * @return The progress listener, if any, or null.
1149:             */
1150:            public ProgressListener getProgressListener() {
1151:                return listener;
1152:            }
1153:
1154:            /**
1155:             * Sets the progress listener.
1156:             * @param pListener The progress listener, if any. Defaults to null.
1157:             */
1158:            public void setProgressListener(ProgressListener pListener) {
1159:                listener = pListener;
1160:            }
1161:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.