View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.util;
20  
21  import java.io.FilterOutputStream;
22  import java.io.IOException;
23  import java.io.OutputStream;
24  import java.nio.charset.StandardCharsets;
25  
26  
27  /* ================================================================ */
28  /** Handle a multipart MIME response.
29   *
30   * 
31   * 
32  */
33  public class MultiPartOutputStream extends FilterOutputStream
34  {
35      /* ------------------------------------------------------------ */
36      private static final byte[] __CRLF={'\r','\n'};
37      private static final byte[] __DASHDASH={'-','-'};
38      
39      public static final String MULTIPART_MIXED="multipart/mixed";
40      public static final String MULTIPART_X_MIXED_REPLACE="multipart/x-mixed-replace";
41      
42      /* ------------------------------------------------------------ */
43      private final String boundary;
44      private final byte[] boundaryBytes;
45  
46      /* ------------------------------------------------------------ */
47      private boolean inPart=false;    
48      
49      /* ------------------------------------------------------------ */
50      public MultiPartOutputStream(OutputStream out)
51      throws IOException
52      {
53          super(out);
54  
55          boundary = "jetty"+System.identityHashCode(this)+
56          Long.toString(System.currentTimeMillis(),36);
57          boundaryBytes=boundary.getBytes(StandardCharsets.ISO_8859_1);
58      }
59  
60      public MultiPartOutputStream(OutputStream out, String boundary)
61           throws IOException
62      {
63          super(out);
64  
65          this.boundary = boundary;
66          boundaryBytes=boundary.getBytes(StandardCharsets.ISO_8859_1);
67      }
68  
69      /* ------------------------------------------------------------ */
70      /** End the current part.
71       * @exception IOException IOException
72       */
73      @Override
74      public void close()
75           throws IOException
76      {
77          try
78          {
79              if (inPart)
80                  out.write(__CRLF);
81              out.write(__DASHDASH);
82              out.write(boundaryBytes);
83              out.write(__DASHDASH);
84              out.write(__CRLF);
85              inPart=false;
86          }
87          finally
88          {
89              super.close();
90          }
91      }
92      
93      /* ------------------------------------------------------------ */
94      public String getBoundary()
95      {
96          return boundary;
97      }
98  
99      public OutputStream getOut() {return out;}
100     
101     /* ------------------------------------------------------------ */
102     /** Start creation of the next Content.
103      */
104     public void startPart(String contentType)
105          throws IOException
106     {
107         if (inPart)
108             out.write(__CRLF);
109         inPart=true;
110         out.write(__DASHDASH);
111         out.write(boundaryBytes);
112         out.write(__CRLF);
113         if (contentType != null)
114             out.write(("Content-Type: "+contentType).getBytes(StandardCharsets.ISO_8859_1));
115         out.write(__CRLF);
116         out.write(__CRLF);
117     }
118         
119     /* ------------------------------------------------------------ */
120     /** Start creation of the next Content.
121      */
122     public void startPart(String contentType, String[] headers)
123          throws IOException
124     {
125         if (inPart)
126             out.write(__CRLF);
127         inPart=true;
128         out.write(__DASHDASH);
129         out.write(boundaryBytes);
130         out.write(__CRLF);
131         if (contentType != null)
132             out.write(("Content-Type: "+contentType).getBytes(StandardCharsets.ISO_8859_1));
133         out.write(__CRLF);
134         for (int i=0;headers!=null && i<headers.length;i++)
135         {
136             out.write(headers[i].getBytes(StandardCharsets.ISO_8859_1));
137             out.write(__CRLF);
138         }
139         out.write(__CRLF);
140     }
141 
142     /* ------------------------------------------------------------ */
143     @Override
144     public void write(byte[] b, int off, int len) throws IOException
145     {
146         out.write(b,off,len);
147     }
148 }
149 
150 
151 
152