103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.util;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.FilterOutputStream;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.OutputStream;
2403928aee4356845252ac6b662d5c72c29903813eJake Slack
2503928aee4356845252ac6b662d5c72c29903813eJake Slack
2603928aee4356845252ac6b662d5c72c29903813eJake Slack/* ================================================================ */
2703928aee4356845252ac6b662d5c72c29903813eJake Slack/** Handle a multipart MIME response.
2803928aee4356845252ac6b662d5c72c29903813eJake Slack *
2903928aee4356845252ac6b662d5c72c29903813eJake Slack *
3003928aee4356845252ac6b662d5c72c29903813eJake Slack *
3103928aee4356845252ac6b662d5c72c29903813eJake Slack*/
3203928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class MultiPartOutputStream extends FilterOutputStream
3303928aee4356845252ac6b662d5c72c29903813eJake Slack{
3403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
3503928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] __CRLF={'\r','\n'};
3603928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] __DASHDASH={'-','-'};
3703928aee4356845252ac6b662d5c72c29903813eJake Slack
3803928aee4356845252ac6b662d5c72c29903813eJake Slack    public static String MULTIPART_MIXED="multipart/mixed";
3903928aee4356845252ac6b662d5c72c29903813eJake Slack    public static String MULTIPART_X_MIXED_REPLACE="multipart/x-mixed-replace";
4003928aee4356845252ac6b662d5c72c29903813eJake Slack
4103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
4203928aee4356845252ac6b662d5c72c29903813eJake Slack    private String boundary;
4303928aee4356845252ac6b662d5c72c29903813eJake Slack    private byte[] boundaryBytes;
4403928aee4356845252ac6b662d5c72c29903813eJake Slack
4503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
4603928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean inPart=false;
4703928aee4356845252ac6b662d5c72c29903813eJake Slack
4803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
4903928aee4356845252ac6b662d5c72c29903813eJake Slack    public MultiPartOutputStream(OutputStream out)
5003928aee4356845252ac6b662d5c72c29903813eJake Slack    throws IOException
5103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
5203928aee4356845252ac6b662d5c72c29903813eJake Slack        super(out);
5303928aee4356845252ac6b662d5c72c29903813eJake Slack
5403928aee4356845252ac6b662d5c72c29903813eJake Slack        boundary = "jetty"+System.identityHashCode(this)+
5503928aee4356845252ac6b662d5c72c29903813eJake Slack        Long.toString(System.currentTimeMillis(),36);
5603928aee4356845252ac6b662d5c72c29903813eJake Slack        boundaryBytes=boundary.getBytes(StringUtil.__ISO_8859_1);
5703928aee4356845252ac6b662d5c72c29903813eJake Slack
5803928aee4356845252ac6b662d5c72c29903813eJake Slack        inPart=false;
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6003928aee4356845252ac6b662d5c72c29903813eJake Slack
6103928aee4356845252ac6b662d5c72c29903813eJake Slack
6203928aee4356845252ac6b662d5c72c29903813eJake Slack
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    /** End the current part.
6503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @exception IOException IOException
6603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void close()
6903928aee4356845252ac6b662d5c72c29903813eJake Slack         throws IOException
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (inPart)
7203928aee4356845252ac6b662d5c72c29903813eJake Slack            out.write(__CRLF);
7303928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__DASHDASH);
7403928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(boundaryBytes);
7503928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__DASHDASH);
7603928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__CRLF);
7703928aee4356845252ac6b662d5c72c29903813eJake Slack        inPart=false;
7803928aee4356845252ac6b662d5c72c29903813eJake Slack        super.close();
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8003928aee4356845252ac6b662d5c72c29903813eJake Slack
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getBoundary()
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8403928aee4356845252ac6b662d5c72c29903813eJake Slack        return boundary;
8503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8603928aee4356845252ac6b662d5c72c29903813eJake Slack
8703928aee4356845252ac6b662d5c72c29903813eJake Slack    public OutputStream getOut() {return out;}
8803928aee4356845252ac6b662d5c72c29903813eJake Slack
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Start creation of the next Content.
9103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
9203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void startPart(String contentType)
9303928aee4356845252ac6b662d5c72c29903813eJake Slack         throws IOException
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (inPart)
9603928aee4356845252ac6b662d5c72c29903813eJake Slack            out.write(__CRLF);
9703928aee4356845252ac6b662d5c72c29903813eJake Slack        inPart=true;
9803928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__DASHDASH);
9903928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(boundaryBytes);
10003928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__CRLF);
10103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (contentType != null)
10203928aee4356845252ac6b662d5c72c29903813eJake Slack            out.write(("Content-Type: "+contentType).getBytes(StringUtil.__ISO_8859_1));
10303928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__CRLF);
10403928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__CRLF);
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10603928aee4356845252ac6b662d5c72c29903813eJake Slack
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Start creation of the next Content.
10903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void startPart(String contentType, String[] headers)
11103928aee4356845252ac6b662d5c72c29903813eJake Slack         throws IOException
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (inPart)
11403928aee4356845252ac6b662d5c72c29903813eJake Slack            out.write(__CRLF);
11503928aee4356845252ac6b662d5c72c29903813eJake Slack        inPart=true;
11603928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__DASHDASH);
11703928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(boundaryBytes);
11803928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__CRLF);
11903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (contentType != null)
12003928aee4356845252ac6b662d5c72c29903813eJake Slack            out.write(("Content-Type: "+contentType).getBytes(StringUtil.__ISO_8859_1));
12103928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__CRLF);
12203928aee4356845252ac6b662d5c72c29903813eJake Slack        for (int i=0;headers!=null && i<headers.length;i++)
12303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
12403928aee4356845252ac6b662d5c72c29903813eJake Slack            out.write(headers[i].getBytes(StringUtil.__ISO_8859_1));
12503928aee4356845252ac6b662d5c72c29903813eJake Slack            out.write(__CRLF);
12603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
12703928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(__CRLF);
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12903928aee4356845252ac6b662d5c72c29903813eJake Slack
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void write(byte[] b, int off, int len) throws IOException
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13403928aee4356845252ac6b662d5c72c29903813eJake Slack        out.write(b,off,len);
13503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13603928aee4356845252ac6b662d5c72c29903813eJake Slack}
13703928aee4356845252ac6b662d5c72c29903813eJake Slack
13803928aee4356845252ac6b662d5c72c29903813eJake Slack
13903928aee4356845252ac6b662d5c72c29903813eJake Slack
14003928aee4356845252ac6b662d5c72c29903813eJake Slack
141