Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/meterware/httpunit/MimeEncodedMessageBody.java


1   package com.meterware.httpunit;
2   /********************************************************************************************************************
3   * $Id: MimeEncodedMessageBody.java,v 1.15 2002/11/15 02:53:59 russgold Exp $
4   *
5   * Copyright (c) 2000-2001, Russell Gold
6   *
7   * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8   * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9   * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
10  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all copies or substantial portions
13  * of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
16  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
18  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19  * DEALINGS IN THE SOFTWARE.
20  *
21  *******************************************************************************************************************/
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  
26  /**
27   * A POST-method message body which is MIME-encoded. This is used when uploading files, and is selected when the enctype
28   * parameter of a form is set to "multi-part/form-data".
29   **/
30  class MimeEncodedMessageBody extends MessageBody {
31  
32  
33      public MimeEncodedMessageBody( PostMethodWebRequest request ) {
34          super( request );
35      }
36  
37  
38      /**
39       * Returns the content type of this message body.
40       **/
41      String getContentType() {
42          return "multipart/form-data; boundary=" + BOUNDARY;
43      }
44  
45  
46      /**
47       * Returns the request associated with this message body, cast to a POST request.
48       **/
49      PostMethodWebRequest getPostRequest() {
50          return (PostMethodWebRequest) getRequest();
51      }
52  
53  
54      /**
55       * Transmits the body of this request as a sequence of bytes.
56       **/
57      void writeTo( OutputStream outputStream ) throws IOException {
58          MimeEncoding encoding = new MimeEncoding( outputStream );
59          getRequest().getParameterHolder().recordParameters( encoding );
60          encoding.sendClose();
61      }
62  
63  
64      private final static String BOUNDARY = "--HttpUnit-part0-aSgQ2M";
65      private final static byte[] CRLF     = { 0x0d, 0x0A };
66  
67  
68      private String encode( String string ) {
69          char[] chars = string.toCharArray();
70          StringBuffer sb = new StringBuffer(chars.length+20);
71          for (int i = 0; i < chars.length; i++ ) {
72              if (chars[i] == '\\') {
73                  sb.append( "\\\\" );    // accomodate MS-DOS file paths ??? is this safe??
74              } else {
75                  sb.append( chars[i] );
76              }
77          }
78          return sb.toString();
79      }
80  
81  
82      private void writeLn( OutputStream os, String value, String encoding ) throws IOException {
83          os.write( value.getBytes( encoding ) );
84          os.write( CRLF );
85      }
86  
87  
88      private void writeLn( OutputStream os, String value ) throws IOException {
89          writeLn( os, value, getRequest().getCharacterSet() );
90      }
91  
92  
93      class MimeEncoding implements ParameterProcessor {
94  
95          public MimeEncoding( OutputStream outputStream ) {
96              _outputStream = outputStream;
97          }
98  
99  
100         public void sendClose() throws IOException {
101             writeLn( _outputStream, "--" + BOUNDARY + "--" );
102         }
103 
104 
105         public void addParameter( String name, String value, String characterSet ) throws IOException {
106             if (name == null || name.length() == 0) return;
107 
108             writeLn( _outputStream, "--" + BOUNDARY );
109             writeLn( _outputStream, "Content-Disposition: form-data; name=\"" + name + '"' );  // XXX need to handle non-ascii names here
110             writeLn( _outputStream, "Content-Type: text/plain; charset=" + getRequest().getCharacterSet() );
111             writeLn( _outputStream, "" );
112             writeLn( _outputStream, fixLineEndings( value ), getRequest().getCharacterSet() );
113         }
114 
115 
116         private final static char CR = 0x0D;
117         private final static char LF = 0x0A;
118 
119         private String fixLineEndings( String value ) {
120             StringBuffer sb = new StringBuffer();
121             char[] chars = value.toCharArray();
122             for (int i = 0; i < chars.length; i++) {
123                 if (chars[i] == CR || (chars[i] == LF && (i == 0 || chars[i-1] != CR))) {
124                     sb.append( CR ).append( LF );
125                 } else {
126                     sb.append( chars[i] );
127                 }
128             }
129             return sb.toString();
130         }
131 
132 
133         public void addFile( String name, UploadFileSpec spec ) throws IOException {
134             byte[] buffer = new byte[ 8 * 1024 ];
135 
136             writeLn( _outputStream, "--" + BOUNDARY );
137             writeLn( _outputStream, "Content-Disposition: form-data; name=\"" + encode( name ) + "\"; filename=\"" + encode( spec.getFileName() ) + '"' );   // XXX need to handle non-ascii names here
138             writeLn( _outputStream, "Content-Type: " + spec.getContentType() );
139             writeLn( _outputStream, "" );
140 
141             InputStream in = spec.getInputStream();
142             int count = 0;
143             do {
144                 _outputStream.write( buffer, 0, count );
145                 count = in.read( buffer, 0, buffer.length );
146             } while (count != -1);
147 
148             in.close();
149             writeLn( _outputStream, "" );
150         }
151 
152         private OutputStream _outputStream;
153     }
154 
155 }
156