Package com.emc.atmos.api.multipart

Source Code of com.emc.atmos.api.multipart.MultipartEntity

/*
* Copyright 2013 EMC Corporation. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.emc.atmos.api.multipart;

import com.emc.atmos.api.Range;
import com.emc.util.StreamUtil;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Represents a multipart response entity.
*/
public class MultipartEntity extends ArrayList<MultipartPart> {
    private static final long serialVersionUID = -4788353053749563899L;

    private static final Pattern PATTERN_CONTENT_TYPE = Pattern.compile( "^Content-Type: (.+)$" );
    private static final Pattern PATTERN_CONTENT_RANGE = Pattern.compile( "^Content-Range: bytes (\\d+)-(\\d+)/(\\d+)$" );

    /**
     * Parses a multipart response body provided by an InputStream. Returns an instance of this class that represents
     * the response. boundary may start with "--" or omit it.
     */
    public static MultipartEntity fromStream( InputStream is, String boundary ) throws IOException {
        if ( boundary.startsWith( "--" ) ) boundary = boundary.substring( 2 );

        List<MultipartPart> parts = new ArrayList<MultipartPart>();

        try {
            while ( true ) {

                // first, we expect a boundary ( EOL + '--' + <boundary_string> + EOL )
                if ( !"".equals( StreamUtil.readLine( is ) ) )
                    throw new MultipartException( "Parse error: expected EOL before boundary" );
                String line = StreamUtil.readLine( is );

                // two dashes after the boundary means EOS
                if ( ("--" + boundary + "--").equals( line ) ) break;

                if ( !("--" + boundary).equals( line ) ) throw new MultipartException(
                        "Parse error: expected [--" + boundary + "], instead got [" + line + "]" );

                Matcher matcher;
                String contentType = null;
                int start = -1, end = 0, length = 0;
                while ( !"".equals( line = StreamUtil.readLine( is ) ) ) {
                    matcher = PATTERN_CONTENT_TYPE.matcher( line );
                    if ( matcher.find() ) {
                        contentType = matcher.group( 1 );
                        continue;
                    }

                    matcher = PATTERN_CONTENT_RANGE.matcher( line );
                    if ( matcher.find() ) {
                        start = Integer.parseInt( matcher.group( 1 ) );
                        end = Integer.parseInt( matcher.group( 2 ) );
                        length = end - start + 1;
                        // total = Integer.parseInt( matcher.group( 3 ) );
                        continue;
                    }

                    throw new MultipartException( "Unrecognized header line: " + line );
                }

                if ( contentType == null )
                    throw new MultipartException( "Parse error: No content-type specified in part" );

                if ( start == -1 )
                    throw new MultipartException( "Parse error: No content-range specified in part" );

                // then the data of the part
                byte[] data = new byte[length];
                int read, count = 0;
                while ( count < length ) {
                    read = is.read( data, 0, length - count );
                    count += read;
                }

                parts.add( new MultipartPart( contentType, new Range( start, end ), data ) );
            }
        } finally {
            is.close();
        }

        return new MultipartEntity( parts );
    }

    public MultipartEntity( List<MultipartPart> parts ) {
        super( parts );
    }

    /**
     * Convenience method that aggregates the bytes of all parts into one contiguous byte array.
     */
    public byte[] aggregateBytes() {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            for ( MultipartPart part : this ) {
                baos.write( part.getData() );
            }
            return baos.toByteArray();
        } catch ( IOException e ) {
            throw new RuntimeException( "Unexpected error", e ); // unrecoverable
        }
    }
}
TOP

Related Classes of com.emc.atmos.api.multipart.MultipartEntity

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.