/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml.ws.http.fragment; import gw.internal.xml.ws.http.HttpParseContext; import gw.util.Pair; import gw.xml.ws.WebServiceException; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; public class HttpMultipartRelatedContent extends HttpFragment { private final List<HttpHeadersAndBody> _parts = new ArrayList<HttpHeadersAndBody>(); private final String _start; public HttpMultipartRelatedContent( HttpParseContext context, HttpMediaType contentType ) throws EOFException { String boundary = contentType.getFirstParameter( "boundary" ); if ( boundary == null ) { throw new WebServiceException( "Boundary not specified." ); } byte[] boundaryBytes; try { boundaryBytes = boundary.getBytes( "US-ASCII" ); } catch ( UnsupportedEncodingException e ) { throw new RuntimeException( e ); // shouldn't happen with US-ASCII } _start = contentType.getFirstParameter( "start" ); ByteArrayOutputStream currentHttpHeadersAndBody = null; while ( true ) { if ( context.get() == null ) { throw new EOFException( "Unexpected end of file" ); } if ( boundaryStart( context, currentHttpHeadersAndBody == null ) ) { boolean boundaryFound = true; for ( byte boundaryByte : boundaryBytes ) { if ( context.get() == null || context.get() != boundaryByte ) { boundaryFound = false; break; } context.next(); } if ( boundaryFound ) { if ( currentHttpHeadersAndBody != null ) { byte[] currentHttpHeadersAndBodyBytes = currentHttpHeadersAndBody.toByteArray(); HttpHeadersAndBody message = new HttpHeadersAndBody( new HttpParseContext( currentHttpHeadersAndBodyBytes ) ); _parts.add( message ); } if ( consumeOptionalChar( context, (byte) '-' ) ) { consumeChar( context, (byte) '-' ); break; // final boundary found } consumeChar( context, (byte) 13 ); consumeChar( context, (byte) 10 ); context.mark(); currentHttpHeadersAndBody = new ByteArrayOutputStream(); continue; } context.reset(); } currentHttpHeadersAndBody.write( context.get() ); context.next(); } } private boolean boundaryStart( HttpParseContext context, boolean firstBoundary ) { if ( context.get() == 13 || context.get() == '-' ) { // possible boundary start context.mark(); if ( context.get() == 13 ) { context.next(); if ( context.get() == 10 ) { context.next(); } else { context.reset(); return false; } } else if ( ! firstBoundary ) { context.reset(); // CRLF is required before boundary, unless first boundary return false; } if ( context.get() == '-' ) { context.next(); if ( context.get() == '-' ) { context.next(); return true; } } context.reset(); } return false; } public HttpHeadersAndBody getRootPart() { if ( _start == null ) { return _parts.get( 0 ); // TODO - check the spec to make sure this is right } for ( HttpHeadersAndBody part : _parts ) { for ( Pair<HttpToken, HttpFieldValue> header : part.getHttpHeaders()){ if ( header.getFirst().getText().equalsIgnoreCase( "content-id" ) ) { if ( header.getSecond().getText().equals( _start ) ) { return part; } } } } throw new WebServiceException( "Root part not found with content-id '" + _start + "'" ); } public List<HttpHeadersAndBody> getParts() { return _parts; } }