View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments;
14  
15  import com.eviware.soapui.SoapUI;
16  import com.eviware.soapui.impl.support.AbstractHttpOperation;
17  import com.eviware.soapui.impl.wsdl.WsdlOperation;
18  import com.eviware.soapui.model.iface.Attachment;
19  import com.eviware.soapui.model.iface.Attachment.AttachmentType;
20  import com.eviware.soapui.support.StringUtils;
21  import com.eviware.soapui.support.Tools;
22  import com.eviware.soapui.support.xml.XmlUtils;
23  
24  import javax.activation.DataSource;
25  import javax.mail.BodyPart;
26  import javax.mail.MessagingException;
27  import javax.mail.internet.MimeMessage;
28  import javax.mail.internet.MimeMultipart;
29  import java.io.ByteArrayOutputStream;
30  import java.io.InputStream;
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  /***
35   * Utility class for managing large MultiParts
36   * 
37   * @author ole.matzura
38   */
39  
40  public class MultipartMessageSupport 
41  {
42  	private final List<BodyPartAttachment> attachments = new ArrayList<BodyPartAttachment>();
43  	private Attachment rootPart;
44  	private MimeMessage message;
45  	private String responseContent;
46  	private final boolean prettyPrint;
47  
48  	public MultipartMessageSupport( DataSource dataSource, String rootPartId, AbstractHttpOperation operation, boolean isRequest, boolean prettyPrint ) throws MessagingException
49  	{
50  		this.prettyPrint = prettyPrint;
51  		MimeMultipart mp = new MimeMultipart( dataSource);
52  		message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
53  		message.setContent( mp );
54  		
55  		AttachmentType attachmentType = AttachmentType.MIME;
56  		
57  		for( int c = 0; c < mp.getCount(); c++ )
58  		{
59  			BodyPart bodyPart = mp.getBodyPart( c );
60  			
61  			String contentType = bodyPart.getContentType().toUpperCase();
62  			if( contentType.startsWith( "APPLICATION/XOP+XML"))
63  				attachmentType = AttachmentType.XOP;
64  			
65  			if( contentType.startsWith( "MULTIPART/"))
66  			{
67  				MimeMultipart mp2 = new MimeMultipart( new BodyPartDataSource( bodyPart ));
68  				for( int i = 0; i < mp2.getCount(); i++ )
69  				{
70  					attachments.add( new BodyPartAttachment( mp2.getBodyPart(i), operation, isRequest, attachmentType ));
71  				}
72  			}
73  			else 
74  			{
75  				BodyPartAttachment attachment = new BodyPartAttachment( bodyPart, operation, isRequest, attachmentType );
76  				
77  				String[] contentIdHeaders = bodyPart.getHeader( "Content-ID");
78  				if( contentIdHeaders != null && contentIdHeaders.length > 0 && contentIdHeaders[0].equals( rootPartId ))
79  				{
80  					rootPart = attachment;
81  				}
82  				else
83  					attachments.add( attachment );
84  			}
85  		}
86  		
87  		// if no explicit root part has been set, use the first one in the result
88  		if( rootPart == null )
89  			rootPart = attachments.remove( 0 );
90  		
91  		((BodyPartAttachment)rootPart).setAttachmentType( AttachmentType.CONTENT );
92  	}
93  	
94  	public void setOperation( WsdlOperation operation )
95  	{
96  		for( BodyPartAttachment attachment : attachments )
97  		{
98  			attachment.setOperation( operation );
99  		}
100 	}
101 
102 	public Attachment[] getAttachments()
103 	{
104 		return attachments.toArray( new Attachment[attachments.size()]);
105 	}
106 
107 	public Attachment getRootPart()
108 	{
109 		return rootPart;
110 	}
111 
112 	public Attachment[] getAttachmentsForPart(String partName)
113 	{
114 		List<Attachment> results = new ArrayList<Attachment>();
115 		
116 		for( Attachment attachment : attachments )
117 		{
118 			if( attachment.getPart().equals( partName ))
119 				results.add( attachment );
120 		}
121 		
122 		return results.toArray( new Attachment[results.size()]);
123 	}
124 
125 	public String getContentAsString()
126 	{
127 		if( rootPart == null )
128 			return null;
129 		
130 		if( responseContent == null )
131 		{
132 			try
133 			{
134 				InputStream in = rootPart.getInputStream();
135 				ByteArrayOutputStream out = Tools.readAll( in, Tools.READ_ALL );
136 				byte [] data = out.toByteArray();
137 				int contentOffset = 0;
138 				
139 				String contentType = rootPart.getContentType();
140 				if( contentType != null && data.length  > 0 )
141 				{
142 					String charset = null;
143 					if( contentType.indexOf( "charset=" ) > 0)
144 					{
145 						try
146 						{
147 							int ix = contentType.indexOf( "charset=" );
148 							int ix2 = contentType.indexOf( ";", ix );
149 						
150 							charset = ix2 == -1 ? contentType.substring( ix+8 ) : 
151 								contentType.substring( ix+8, ix2 );
152 						}
153 						catch( Throwable e )
154 						{
155 							SoapUI.logError( e );
156 						}
157 					}
158 					
159 					int ix = contentType.indexOf( ';');
160 					if( ix > 0 )
161 					{
162 						contentType = contentType.substring(0, ix);
163 						if( contentType.toLowerCase().endsWith("xml"))
164 						{
165 							if( data.length > 3 && data[0] == (byte)239 && data[1] == (byte)187 && data[2] == (byte)191 )
166 							{
167 								charset = "UTF-8";
168 								contentOffset = 3;
169 							}
170 						}
171 					}
172 					
173 					charset = StringUtils.unquote( charset );
174 					
175 					responseContent = charset == null ? new String(data) : 
176 						new String(	data, contentOffset, (int)(data.length-contentOffset), charset );
177 				}
178 				
179 				if( responseContent == null )
180 				{
181 					responseContent = data.toString();
182 				}
183 				
184 				if( prettyPrint )
185 		   	{
186 					responseContent = XmlUtils.prettyPrintXml( responseContent );
187 		   	}
188 				
189 				return responseContent;
190 			}
191 			catch (Exception e)
192 			{
193 				SoapUI.logError( e );
194 			}
195 		}
196 		
197 		return responseContent;
198 	}
199 	
200 	public void setResponseContent(String responseContent)
201 	{
202 		this.responseContent = responseContent;
203 	}
204 
205 	public Attachment getAttachmentWithContentId( String contentId )
206 	{
207 		for( Attachment attachment : attachments)
208 		   if( contentId.equals( attachment.getContentID() ))
209 		   	return attachment;
210 		
211 		return null;
212 	}
213 }