Source Code Cross Referenced for MultiPartHandler.java in  » IDE-Netbeans » cvsclient » org » netbeans » lib » uihandler » 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 » IDE Netbeans » cvsclient » org.netbeans.lib.uihandler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * Portions Copyrighted 2007 Sun Microsystems, Inc.
027:         */
028:
029:        package org.netbeans.lib.uihandler;
030:
031:        /*
032:         * MultipartHandler:
033:         * A utility class to handle content of multipart/form-data type used in form uploads. 
034:         *
035:         * Parses and provides accessor functions to extract the form fields and the uploaded
036:         * file content parts separated by a boundary string.
037:         * See http://www.ietf.org/rfc/rfc1867.txt.
038:         */
039:
040:        import java.io.BufferedOutputStream;
041:        import java.io.ByteArrayOutputStream;
042:        import java.io.File;
043:        import java.io.FileOutputStream;
044:        import java.io.FilterInputStream;
045:        import java.io.IOException;
046:        import java.io.InputStream;
047:        import java.io.OutputStream;
048:        import java.util.Enumeration;
049:        import java.util.Hashtable;
050:        import java.util.HashMap;
051:        import java.util.Vector;
052:        import java.util.zip.GZIPInputStream;
053:
054:        public class MultiPartHandler {
055:            public interface InputFacade {
056:                public int readLine(byte[] arr, int off, int len)
057:                        throws IOException;
058:
059:                public InputStream getInputStream();
060:            }
061:
062:            public interface RequestFacade {
063:                public int getContentLength();
064:
065:                public String getContentType();
066:
067:                public InputFacade getInput() throws IOException;
068:            }
069:
070:            private static final int DEFAULT_MAX_UPLOAD_SIZE = 1024 * 1024; // 1Mb
071:
072:            protected Hashtable<String, Vector<String>> formFields = new Hashtable<String, Vector<String>>();
073:            Hashtable<String, OneUpload> uploadFiles = new Hashtable<String, OneUpload>();
074:
075:            /** servlet request */
076:            private RequestFacade req;
077:
078:            /** input stream to read parts from */
079:            private InputFacade in;
080:
081:            /** MIME boundary that delimits parts */
082:            private String boundary;
083:
084:            /** buffer for readLine method */
085:            private byte[] buf = new byte[8 * 1024];
086:
087:            /** upload directory */
088:            private File uploadDir;
089:
090:            /** encoding used for the from fields */
091:            private String fieldEncoding = "ISO-8859-1";
092:
093:            // i18n StringManager
094:            /*private static StringManager localStrings =
095:            StringManager.getManager( OneUpload.class );*/
096:
097:            /** 
098:             * Instantiate a new multipart handler with default
099:             */
100:            public MultiPartHandler(RequestFacade request, String tmpDirectory)
101:                    throws IOException {
102:                this (request, tmpDirectory, DEFAULT_MAX_UPLOAD_SIZE,
103:                        "ISO-8859-1");
104:            }
105:
106:            public MultiPartHandler(RequestFacade request, String tmpDirectory,
107:                    int maxUploadSize) throws IOException {
108:                this (request, tmpDirectory, maxUploadSize, "ISO-8859-1");
109:            }
110:
111:            /**
112:             * Instantiate a new OneUpload to handle the given request,
113:             * saving any uploaded files to the given directory and limiting the 
114:             * upload size to maxUploadSize. 
115:             *
116:             * An IOException is thrown when the request content-type doesn't match
117:             * with multipart/form-data or if the upload size exceeds the given limit.
118:             *
119:             * call parseMultipartUpload() to parse various parts of the posted data and then
120:             * call getParameter(), getParameters(), getParameterNames() and getParameterValues()
121:             *      functions to access form field names and their values.
122:             * call getFile(), getFileType() to access uploaded file and its content-type.
123:             */
124:            public MultiPartHandler(RequestFacade request, String tmpDirectory,
125:                    int maxUploadSize, String fieldEncoding) throws IOException {
126:
127:                // Ensure we are passed legal arguments
128:                if (request == null) {
129:                    //String msg = localStrings.getString( "admin.server.gui.servlet.request_cannot_be_null" );
130:                    throw new IllegalArgumentException("request is null");
131:                }
132:                if (tmpDirectory == null) {
133:                    //String msg = localStrings.getString( "admin.server.gui.servlet.tmpdirectory_cannot_be_null" );
134:                    throw new IllegalArgumentException("tmp Dir is null");
135:                }
136:                if (maxUploadSize <= 0) {
137:                    //String msg = localStrings.getString( "admin.server.gui.servlet.maxpostsize_must_be_positive" );
138:                    throw new IllegalArgumentException("Max size is < 0");
139:                }
140:
141:                // Ensure that the directory exists and is writable (this should be a temp directory)
142:                uploadDir = new File(tmpDirectory);
143:                if (!uploadDir.isDirectory()) {
144:                    //String msg = localStrings.getString( "admin.server.gui.servlet.not_directory", tmpDirectory );
145:                    throw new IllegalArgumentException("Not a Directory");
146:                }
147:                if (!uploadDir.canWrite()) {
148:                    //String msg = localStrings.getString( "admin.server.gui.servlet.not_writable", tmpDirectory );
149:                    throw new IllegalArgumentException("write protected");
150:                }
151:                /*
152:                int length = request.getContentLength();
153:                //commented this code to remove the restriction on the file upload size.
154:                /*if (length > maxUploadSize) {
155:                  //String msg = localStrings.getString( "admin.server.gui.servlet.posted_content_length_exceeds_limit", new Integer(length), new Integer(maxUploadSize) );
156:                  throw new IOException( msg );
157:                }*/
158:                // Check the content type to make sure it's "multipart/form-data"
159:                String type = request.getContentType();
160:                if (type == null
161:                        || !type.toLowerCase()
162:                                .startsWith("multipart/form-data")) {
163:                    //String msg = localStrings.getString( "admin.server.gui.servlet.posted_content_type_not_multipart" );
164:                    throw new IOException("type null");
165:                }
166:
167:                // Check the content length to prevent denial of service attacks
168:                this .fieldEncoding = fieldEncoding;
169:                this .req = request;
170:            }
171:
172:            /* parseMultipartUpload:
173:             *
174:             * This function parses the multipart/form-data and throws an IOException 
175:             * if there's any problem reading or parsing the request or if the posted
176:             * content is larger than the maximum permissible size.
177:             */
178:            public void parseMultipartUpload() throws IOException {
179:                // setup the initial buffered input stream, boundary string that separates
180:                // various parts in the stream.
181:                startMultipartParse();
182:
183:                HashMap partHeaders = parsePartHeaders();
184:                while (partHeaders != null) {
185:
186:                    String fieldName = (String) partHeaders.get("fieldName");
187:                    String fileName = (String) partHeaders.get("fileName");
188:
189:                    if (fileName != null) {
190:                        // This is a file upload part
191:                        if (fileName.equals("")) {
192:                            fileName = null; // empty filename, probably an "empty" file param
193:                        }
194:
195:                        if (fileName != null) {
196:                            // a filename was actually specified
197:                            String content = (String) partHeaders
198:                                    .get("content-type");
199:                            fileName = saveUploadFile(fileName, content);
200:
201:                            uploadFiles.put(fieldName, new OneUpload(uploadDir
202:                                    .toString(), fileName, content));
203:                        } else {
204:                            uploadFiles.put(fieldName, new OneUpload(null,
205:                                    null, null));
206:                        }
207:                    } else {
208:                        // this is a parameters list part
209:                        byte[] valueBytes = parseFormFieldBytes();
210:                        String value = new String(valueBytes, fieldEncoding);
211:
212:                        Vector<String> existingValues = formFields
213:                                .get(fieldName);
214:                        if (existingValues == null) {
215:                            existingValues = new Vector<String>();
216:                            formFields.put(fieldName, existingValues);
217:                        }
218:                        existingValues.addElement(value);
219:                    }
220:
221:                    partHeaders.clear();
222:                    partHeaders = parsePartHeaders();
223:                }
224:            }
225:
226:            private void startMultipartParse() throws IOException {
227:                // Get the boundary string; it's included in the content type.
228:                // Should look something like "------------------------12012133613061"
229:                String boundary = parseBoundary(req.getContentType());
230:                if (boundary == null) {
231:                    //String msg = localStrings.getString( "admin.server.gui.servlet.separation_boundary_not_specified" );
232:                    throw new IOException("boundary is nul");
233:                }
234:
235:                this .in = req.getInput();
236:                this .boundary = boundary;
237:
238:                // Read the first line, should be the first boundary
239:                String line = readLine();
240:                if (line == null) {
241:                    //String msg = localStrings.getString( "admin.server.gui.servlet.corrupt_form_data_premature_ending" );
242:                    throw new IOException("line is null");
243:                }
244:
245:                // Verify that the line is the boundary
246:                if (!line.startsWith(boundary)) {
247:                    //String msg = localStrings.getString( "admin.server.gui.servlet.corrupt_form_data_no_leading_boundary", line, boundary );
248:                    throw new IOException("not start with boundary");
249:                }
250:            }
251:
252:            /**
253:             * parse the headers of the individual part; they look like this:
254:             * Content-Disposition: form-data; name="field1"; filename="file1.txt"
255:             * Content-Type: type/subtype
256:             * Content-Transfer-Encoding: binary
257:             */
258:            private HashMap parsePartHeaders() throws IOException {
259:                HashMap<String, String> partHeaders = new HashMap<String, String>();
260:
261:                Vector<String> headers = new Vector<String>();
262:                String line = readLine();
263:                if (line == null) {
264:                    // No parts left, we're done
265:                    return null;
266:                } else if (line.length() == 0) {
267:                    // IE4 on Mac sends an empty line at the end; treat that as the end.
268:                    return null;
269:                }
270:                headers.addElement(line);
271:
272:                // Read the following header lines we hit an empty line
273:                while ((line = readLine()) != null && (line.length() > 0)) {
274:                    headers.addElement(line);
275:                }
276:
277:                // If we got a null above, it's the end
278:                if (line == null) {
279:                    return null;
280:                }
281:
282:                // default part content type (rfc1867)
283:                partHeaders.put("content-type", "text/plain");
284:
285:                Enumeration ee = headers.elements();
286:                while (ee.hasMoreElements()) {
287:                    String headerline = (String) ee.nextElement();
288:
289:                    if (headerline.toLowerCase().startsWith(
290:                            "content-disposition:")) {
291:                        // Parse the content-disposition line
292:                        parseContentDisposition(headerline, partHeaders);
293:                    } else if (headerline.toLowerCase().startsWith(
294:                            "content-type:")) {
295:                        // Get the content type, or null if none specified
296:                        parseContentType(headerline, partHeaders);
297:                    }
298:                }
299:
300:                return partHeaders;
301:            }
302:
303:            /**
304:             * parses and returns the boundary token from a line.
305:             */
306:            private String parseBoundary(String line) {
307:                // Use lastIndexOf() because IE 4.01 on Win98 has been known to send the
308:                // "boundary=" string multiple times.
309:                int index = line.lastIndexOf("boundary=");
310:                if (index == -1) {
311:                    return null;
312:                }
313:                String boundary = line.substring(index + 9); // 9 for "boundary="
314:                if (boundary.charAt(0) == '"') {
315:                    // The boundary is enclosed in quotes, strip them
316:                    index = boundary.lastIndexOf('"');
317:                    boundary = boundary.substring(1, index);
318:                }
319:
320:                // The real boundary is always preceeded by an extra "--"
321:                boundary = "--" + boundary;
322:
323:                return boundary;
324:            }
325:
326:            /**
327:             * parses and returns content-disposition header and stores the values
328:             * in the partHeaders.
329:             * 
330:             * throws IOException if the line is malformatted.
331:             */
332:            private void parseContentDisposition(String line,
333:                    HashMap<String, String> partHeaders) throws IOException {
334:
335:                // Convert the line to a lowercase string without the ending \r\n
336:                // Keep the original line for error messages and for variable names.
337:                String origline = line;
338:                line = origline.toLowerCase();
339:
340:                // Get the content disposition, should be "form-data"
341:                int start = line.indexOf("content-disposition: ");
342:                int end = line.indexOf(";");
343:                if (start == -1 || end == -1) {
344:                    //String msg = localStrings.getString( "admin.server.gui.servlet.content_disposition_corrupt", origline );
345:                    throw new IOException("end reached");
346:                }
347:                String disposition = line.substring(start + 21, end);
348:                if (!disposition.equals("form-data")) {
349:                    //String msg = localStrings.getString( "admin.server.gui.servlet.invalid_content_disposition", disposition );
350:                    throw new IOException("fome-data not match");
351:                }
352:
353:                // Get the field name
354:                start = line.indexOf("name=\"", end); // start at last semicolon
355:                end = line.indexOf("\"", start + 7); // skip name=\"
356:                if (start == -1 || end == -1) {
357:                    //String msg = localStrings.getString( "admin.server.gui.servlet.content_disposition_corrupt", origline );	
358:                    throw new IOException("data corrupt");
359:                }
360:
361:                String name = origline.substring(start + 6, end);
362:
363:                // Get the fileName, if given
364:                String fileName = null;
365:                String origFileName = null;
366:                start = line.indexOf("filename=\"", end + 2); // start after name
367:                end = line.indexOf("\"", start + 10); // skip filename=\"
368:
369:                if (start != -1 && end != -1) { // note the !=
370:                    fileName = origline.substring(start + 10, end);
371:                    origFileName = fileName;
372:                    // The filename may contain a full path.  Cut to just the filename.
373:                    int slash = Math.max(fileName.lastIndexOf('/'), fileName
374:                            .lastIndexOf('\\'));
375:                    if (slash > -1) {
376:                        fileName = fileName.substring(slash + 1); // past last slash
377:                    }
378:                }
379:
380:                // fill in the part parameters map: disposition, name, filename
381:                // empty fileName denotes no file posted!
382:                partHeaders.put("disposition", disposition);
383:                partHeaders.put("fieldName", name);
384:                partHeaders.put("fileName", fileName);
385:                partHeaders.put("filePath", origFileName);
386:            }
387:
388:            /**
389:             * parse and returns the content type from a line, or null if the
390:             * line was empty.
391:             */
392:            private void parseContentType(String line,
393:                    HashMap<String, String> partHeaders) throws IOException {
394:                String contentType = null;
395:
396:                // Convert the line to a lowercase string
397:                String origline = line;
398:                line = origline.toLowerCase();
399:
400:                // Get the content type, if any
401:                if (line.startsWith("content-type")) {
402:                    int start = line.indexOf(" ");
403:
404:                    if (start == -1) {
405:                        //String msg = localStrings.getString( "admin.server.gui.servlet.corrupt_content_type", origline );
406:                        throw new IOException("no start");
407:                    }
408:                    contentType = line.substring(start + 1);
409:
410:                    partHeaders.put("content-type", contentType);
411:                } else if (line.length() != 0) { // no content type, so should be empty
412:                    //String msg = localStrings.getString( "admin.server.gui.servlet.malformed_line_after_disposition", origline );
413:                    throw new IOException("length 0");
414:                }
415:            }
416:
417:            /** parse contents of a form field parameter; uses the encoding set by the user
418:             */
419:            private byte[] parseFormFieldBytes() throws IOException {
420:
421:                // Copy the part's contents into a byte array
422:                MultipartInputStream pis = new MultipartInputStream(in,
423:                        boundary);
424:
425:                ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
426:                byte[] buf = new byte[128];
427:                int read;
428:                while ((read = pis.read(buf)) != -1) {
429:                    baos.write(buf, 0, read);
430:                }
431:                pis.close();
432:                baos.close();
433:
434:                // get the value bytes
435:                return baos.toByteArray();
436:            }
437:
438:            /**
439:             * Read the next line of input.
440:             * 
441:             * @return     a String containing the next line of input from the stream,
442:             *        or null to indicate the end of the stream.
443:             * @exception IOException	if an input or output exception has occurred.
444:             */
445:            private String readLine() throws IOException {
446:                StringBuffer sbuf = new StringBuffer();
447:                int result;
448:                String line;
449:
450:                do {
451:                    result = in.readLine(buf, 0, buf.length); // does +=
452:                    if (result != -1) {
453:                        sbuf.append(new String(buf, 0, result, "ISO-8859-1"));
454:                    }
455:                } while (result == buf.length); // loop only if the buffer was filled
456:
457:                if (sbuf.length() == 0) {
458:                    return null; // nothing read, must be at the end of stream
459:                }
460:
461:                // Cut off the trailing \n or \r\n
462:                // It should always be \r\n but IE5 sometimes does just \n
463:                int len = sbuf.length();
464:                if (len >= 2 && sbuf.charAt(len - 2) == '\r') {
465:                    sbuf.setLength(len - 2); // cut \r\n
466:                } else {
467:                    sbuf.setLength(len - 1); // cut \n
468:                }
469:                return sbuf.toString();
470:            }
471:
472:            /**
473:             * Write this file part to the specified directory. 
474:             */
475:            private String saveUploadFile(String fileName, String content)
476:                    throws IOException {
477:
478:                long written = 0;
479:                OutputStream fileOut = null;
480:
481:                try {
482:                    // Only do something if this part contains a file
483:                    File file = new File(uploadDir, fileName);
484:                    for (int i = 0; file.exists(); i++) {
485:                        if (!file.exists()) {
486:                            break;
487:                        }
488:                        file = new File(uploadDir, fileName + "." + i);
489:                    }
490:                    fileName = file.getName();
491:
492:                    fileOut = new BufferedOutputStream(new FileOutputStream(
493:                            file));
494:                    int numBytes;
495:                    byte[] buf = new byte[8 * 1024];
496:
497:                    InputStream partInput;
498:                    if (content.equals("x-application/gzip")) { // NOI18N
499:                        // sending from NetBeans UI Gestures Collector
500:                        partInput = in.getInputStream();
501:                    } else {
502:                        /** input stream containing file data */
503:                        partInput = new MultipartInputStream(in, boundary);
504:                    }
505:                    while ((numBytes = partInput.read(buf)) != -1) {
506:                        fileOut.write(buf, 0, numBytes);
507:                        written += numBytes;
508:                    }
509:                    partInput.close();
510:                } finally {
511:                    if (fileOut != null)
512:                        fileOut.close();
513:                }
514:
515:                return fileName;
516:            }
517:
518:            /**
519:             * Returns the names of all the parameters as an Enumeration of 
520:             * Strings.  It returns an empty Enumeration if there are no parameters.
521:             *
522:             */
523:            public Enumeration getParameterNames() {
524:                return formFields.keys();
525:            }
526:
527:            /**
528:             * Returns the names of all the uploaded files as an Enumeration of 
529:             * Strings.  It returns an empty Enumeration if there are no uploaded 
530:             * files.  Each file name is the name specified by the form, not by 
531:             * the user.
532:             *
533:             */
534:            public Enumeration getFileNames() {
535:                return uploadFiles.keys();
536:            }
537:
538:            /**
539:             * Returns the value of the named parameter as a String, or null if 
540:             * the parameter was not sent or was sent without a value.  The value 
541:             * is guaranteed to be in its normal, decoded form.  If the parameter 
542:             * has multiple values, only the last one is returned (for backward 
543:             * compatibility).  For parameters with multiple values, it's possible
544:             * the last "value" may be null.
545:             *
546:             */
547:            public String getParameter(String name) {
548:                try {
549:                    Vector values = (Vector) formFields.get(name);
550:                    if (values == null || values.size() == 0) {
551:                        return null;
552:                    }
553:                    String value = (String) values.elementAt(values.size() - 1);
554:                    return value;
555:                } catch (Exception e) {
556:                    return null;
557:                }
558:            }
559:
560:            /**
561:             * Returns the values of the named parameter as a String array, or null if 
562:             * the parameter was not sent.  The array has one entry for each parameter 
563:             * field sent.  If any field was sent without a value that entry is stored 
564:             * in the array as a null.  The values are guaranteed to be in their 
565:             * normal, decoded form.  A single value is returned as a one-element array.
566:             *
567:             */
568:            public String[] getParameterValues(String name) {
569:                try {
570:                    Vector values = (Vector) formFields.get(name);
571:                    if (values == null || values.size() == 0) {
572:                        return null;
573:                    }
574:                    String[] valuesArray = new String[values.size()];
575:                    values.copyInto(valuesArray);
576:                    return valuesArray;
577:                } catch (Exception e) {
578:                    return null;
579:                }
580:            }
581:
582:            /**
583:             * Returns the filesystem name of the specified file, or null if the 
584:             * file was not included in the upload.  A filesystem name is the name 
585:             * specified by the user.  It is also the name under which the file is 
586:             * actually saved.
587:             *
588:             */
589:            public String getFileName(String name) {
590:                try {
591:                    OneUpload file = uploadFiles.get(name);
592:                    return file.getFileName(); // may be null
593:                } catch (Exception e) {
594:                    return null;
595:                }
596:            }
597:
598:            /**
599:             * Returns the content type of the specified file (as supplied by the 
600:             * client browser), or null if the file was not included in the upload.
601:             *
602:             */
603:            public String getFileType(String name) {
604:                try {
605:                    OneUpload file = uploadFiles.get(name);
606:                    return file.getFileType(); // may be null
607:                } catch (Exception e) {
608:                    return null;
609:                }
610:            }
611:
612:            /**
613:             * Returns a File object for the specified file saved on the server's 
614:             * filesystem, or null if the file was not included in the upload.
615:             *
616:             */
617:            public File getFile(String name) {
618:                try {
619:                    OneUpload file = uploadFiles.get(name);
620:                    return file.getFile(); // may be null
621:                } catch (Exception e) {
622:                    return null;
623:                }
624:            }
625:
626:            /** 
627:             * close the multi-part form handler
628:             */
629:            public void close() throws IOException {
630:                req = null;
631:                in = null;
632:                boundary = null;
633:                buf = null;
634:                uploadDir = null;
635:            }
636:
637:            /** A class to hold information about an uploaded file. */
638:            private static class OneUpload {
639:
640:                private String dir;
641:                private String filename;
642:                private String type;
643:
644:                OneUpload(String dir, String filename, String type) {
645:                    this .dir = dir;
646:                    this .filename = filename;
647:                    this .type = type;
648:                }
649:
650:                public String getFileType() {
651:                    return type;
652:                }
653:
654:                public String getFileName() {
655:                    return filename;
656:                }
657:
658:                public File getFile() {
659:                    if (dir == null || filename == null) {
660:                        return null;
661:                    } else {
662:                        return new File(dir + File.separator + filename);
663:                    }
664:                }
665:            }
666:
667:            /*
668:             * providing access to a single MIME part contained with in which ends with
669:             * the boundary specified.  It uses buffering to provide maximum performance.
670:             *
671:             */
672:            private static class MultipartInputStream extends FilterInputStream {
673:                /** boundary which "ends" the stream */
674:                private String boundary;
675:
676:                /** our buffer */
677:                private byte[] buf = new byte[64 * 1024]; // 64k
678:
679:                /** number of bytes we've read into the buffer */
680:                private int count;
681:
682:                /** current position in the buffer */
683:                private int pos;
684:
685:                /** flag that indicates if we have encountered the boundary */
686:                private boolean eof;
687:
688:                /** associated facade */
689:                private MultiPartHandler.InputFacade facade;
690:
691:                // i18n StringManager
692:                /*private static StringManager localStrings =
693:                      StringManager.getManager( MultipartInputStream.class );*/
694:
695:                /**
696:                 * Instantiate a MultipartInputStream which stops at the specified
697:                 * boundary from an underlying ServletInputStream.
698:                 *
699:                 */
700:                MultipartInputStream(MultiPartHandler.InputFacade in,
701:                        String boundary) throws IOException {
702:                    super (in.getInputStream());
703:                    this .boundary = boundary;
704:                    this .facade = in;
705:                }
706:
707:                /**
708:                 * Fill up our buffer from the underlying input stream, and check for the
709:                 * boundary that signifies end-of-file. Users of this method must ensure
710:                 * that they leave exactly 2 characters in the buffer before calling this
711:                 * method (except the first time), so that we may only use these characters
712:                 * if a boundary is not found in the first line read.
713:                 *
714:                 * @exception  IOException  if an I/O error occurs.
715:                 */
716:                private void fill() throws IOException {
717:                    if (eof)
718:                        return;
719:
720:                    // as long as we are not just starting up
721:                    if (count > 0) {
722:                        // if the caller left the requisite amount spare in the buffer
723:                        if (count - pos == 2) {
724:                            // copy it back to the start of the buffer
725:                            System.arraycopy(buf, pos, buf, 0, count - pos);
726:                            count -= pos;
727:                            pos = 0;
728:                        } else {
729:                            // should never happen, but just in case
730:                            //String msg = localStrings.getString( "admin.server.gui.servlet.fill_detected_illegal_buffer_state" );
731:                            throw new IllegalStateException(
732:                                    "should never happen");
733:                        }
734:                    }
735:
736:                    // try and fill the entire buffer, starting at count, line by line
737:                    // but never read so close to the end that we might split a boundary
738:                    int read = 0;
739:                    int maxRead = buf.length - boundary.length();
740:                    while (count < maxRead) {
741:                        // read a line
742:                        read = facade.readLine(buf, count, buf.length - count);
743:                        // check for eof and boundary
744:                        if (read == -1) {
745:                            //String msg = localStrings.getString( "admin.server.gui.servlet.unexpected_end_part" );
746:                            throw new IOException("read is -1");
747:                        } else {
748:                            if (read >= boundary.length()) {
749:                                eof = true;
750:                                for (int i = 0; i < boundary.length(); i++) {
751:                                    if (boundary.charAt(i) != buf[count + i]) {
752:                                        // Not the boundary!
753:                                        eof = false;
754:                                        break;
755:                                    }
756:                                }
757:                                if (eof) {
758:                                    break;
759:                                }
760:                            }
761:                        }
762:                        // success
763:                        count += read;
764:                    }
765:                }
766:
767:                /**
768:                 * See the general contract of the read method of InputStream.
769:                 * Returns -1 (end of file) when the MIME boundary of this part is encountered.
770:                 *
771:                 * throws IOException  if an I/O error occurs.
772:                 */
773:                public int read() throws IOException {
774:                    if (count - pos <= 2) {
775:                        fill();
776:                        if (count - pos <= 2) {
777:                            return -1;
778:                        }
779:                    }
780:                    return buf[pos++] & 0xff;
781:                }
782:
783:                /**
784:                 * See the general contract of the read method of InputStream.
785:                 *
786:                 * Returns -1 (end of file) when the MIME boundary of this part
787:                 * is encountered.
788:                 *
789:                 * throws IOException  if an I/O error occurs.
790:                 */
791:                public int read(byte b[]) throws IOException {
792:                    return read(b, 0, b.length);
793:                }
794:
795:                /**
796:                 * See the general contract of the read method of InputStream.
797:                 *
798:                 * Returns -1 (end of file) when the MIME boundary of this part is encountered.
799:                 *
800:                 * throws IOException  if an I/O error occurs.
801:                 */
802:                public int read(byte b[], int off, int len) throws IOException {
803:                    int total = 0;
804:                    if (len == 0) {
805:                        return 0;
806:                    }
807:
808:                    int avail = count - pos - 2;
809:                    if (avail <= 0) {
810:                        fill();
811:                        avail = count - pos - 2;
812:                        if (avail <= 0) {
813:                            return -1;
814:                        }
815:                    }
816:                    int copy = Math.min(len, avail);
817:                    System.arraycopy(buf, pos, b, off, copy);
818:                    pos += copy;
819:                    total += copy;
820:
821:                    while (total < len) {
822:                        fill();
823:                        avail = count - pos - 2;
824:                        if (avail <= 0) {
825:                            return total;
826:                        }
827:                        copy = Math.min(len - total, avail);
828:                        System.arraycopy(buf, pos, b, off + total, copy);
829:                        pos += copy;
830:                        total += copy;
831:                    }
832:                    return total;
833:                }
834:
835:                /**
836:                 * Returns the number of bytes that can be read from this input stream
837:                 * without blocking.  This is a standard InputStream idiom
838:                 * to deal with buffering gracefully, and is not same as the length of the
839:                 * part arriving in this stream.
840:                 *
841:                 * throws IOException  if an I/O error occurs.
842:                 */
843:                public int available() throws IOException {
844:                    int avail = (count - pos - 2) + in.available();
845:                    // Never return a negative value
846:                    return (avail < 0 ? 0 : avail);
847:                }
848:
849:                /**
850:                 * Closes this input stream and releases any system resources
851:                 * associated with the stream. This method will read any unread data
852:                 * in the MIME part so that the next part starts an an expected place in
853:                 * the parent InputStream.
854:                 *
855:                 * throws IOException  if an I/O error occurs.
856:                 */
857:                public void close() throws IOException {
858:                    if (!eof) {
859:                        while (read(buf, 0, buf.length) != -1)
860:                            ; // do nothing
861:                    }
862:                }
863:            }
864:
865:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.