View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.support;
14  
15  import java.io.BufferedInputStream;
16  import java.io.ByteArrayInputStream;
17  import java.io.ByteArrayOutputStream;
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.FileNotFoundException;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.util.zip.ZipEntry;
24  import java.util.zip.ZipInputStream;
25  import java.util.zip.ZipOutputStream;
26  
27  import org.apache.commons.codec.binary.Base64;
28  import org.apache.commons.codec.binary.Hex;
29  import org.apache.log4j.Logger;
30  
31  import com.eviware.soapui.SoapUI;
32  import com.eviware.soapui.config.AttachmentConfig;
33  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
34  import com.eviware.soapui.impl.wsdl.teststeps.BeanPathPropertySupport;
35  import com.eviware.soapui.support.Tools;
36  import com.eviware.soapui.support.editor.inspectors.attachments.ContentTypeHandler;
37  import com.eviware.soapui.support.resolver.ResolveContext;
38  
39  /***
40   * Attachments cached locally for each request
41   * 
42   * @author Ole.Matzura
43   */
44  
45  public abstract class FileAttachment<T extends AbstractWsdlModelItem<?>> implements WsdlAttachment
46  {
47  	private AttachmentConfig config;
48  	private final static Logger log = Logger.getLogger( FileAttachment.class );
49  	private final T modelItem;
50  	private BeanPathPropertySupport urlProperty;
51  
52  	public FileAttachment( T modelItem, AttachmentConfig config )
53  	{
54  		this.modelItem = modelItem;
55  		this.config = config;
56  
57  		if( config.getTempFilename() != null )
58  		{
59  			try
60  			{
61  				log.info( "Moving locally cached file [" + config.getTempFilename() + "] to internal cache.." );
62  				File tempFile = new File( config.getTempFilename() );
63  				cacheFileLocally( tempFile );
64  			}
65  			catch( IOException e )
66  			{
67  				if( !config.isSetData() )
68  				{
69  					config.setData( new byte[0] );
70  					config.setSize( 0 );
71  				}
72  
73  				SoapUI.logError( e );
74  			}
75  		}
76  
77  		if( isCached() )
78  		{
79  			if( config.isSetTempFilename() )
80  				config.unsetTempFilename();
81  
82  			if( config.isSetUrl() )
83  				config.unsetUrl();
84  		}
85  
86  		urlProperty = new BeanPathPropertySupport( modelItem, config, "url" );
87  	}
88  
89  	public FileAttachment( T modelItem, File file, boolean cache, AttachmentConfig config ) throws IOException
90  	{
91  		this( modelItem, config );
92  
93  		config.setName( file.getName() );
94  		config.setContentType( ContentTypeHandler.getContentTypeFromFilename( file.getName() ) );
95  
96  		// cache locally if specified
97  		if( cache )
98  		{
99  			cacheFileLocally( file );
100 		}
101 
102 		urlProperty.set( file.getPath(), false );
103 	}
104 
105 	public void setName( String value )
106 	{
107 		config.setName( value );
108 	}
109 
110 	public void setUrl( String url )
111 	{
112 		urlProperty.set( url, true );
113 	}
114 
115 	public void reload( File file, boolean cache ) throws IOException
116 	{
117 		config.setName( file.getName() );
118 		config.setContentType( ContentTypeHandler.getContentTypeFromFilename( file.getName() ) );
119 
120 		// cache locally if specified
121 		if( cache )
122 		{
123 			cacheFileLocally( file );
124 		}
125 		else
126 		{
127 			urlProperty.set( file.getPath(), false );
128 			config.unsetData();
129 		}
130 	}
131 
132 	public T getModelItem()
133 	{
134 		return modelItem;
135 	}
136 
137 	public void cacheFileLocally( File file ) throws FileNotFoundException, IOException
138 	{
139 		// write attachment-data to tempfile
140 		ByteArrayOutputStream data = new ByteArrayOutputStream();
141 		ZipOutputStream out = new ZipOutputStream( data );
142 		out.putNextEntry( new ZipEntry( config.getName() ) );
143 
144 		InputStream in = new FileInputStream( file );
145 		long sz = file.length();
146 		config.setSize( sz );
147 
148 		Tools.writeAll( out, in );
149 
150 		in.close();
151 		out.closeEntry();
152 		out.finish();
153 		out.close();
154 		data.close();
155 
156 		config.setData( data.toByteArray() );
157 	}
158 
159 	public String getContentType()
160 	{
161 		AttachmentEncoding encoding = getEncoding();
162 		if( encoding == AttachmentEncoding.NONE )
163 			return config.getContentType();
164 		else
165 			return "application/octet-stream";
166 	}
167 
168 	public InputStream getInputStream() throws IOException
169 	{
170 		BufferedInputStream inputStream = null;
171 
172 		if( isCached() )
173 		{
174 			ZipInputStream zipInputStream = new ZipInputStream( new ByteArrayInputStream( config.getData() ) );
175 			zipInputStream.getNextEntry();
176 			inputStream = new BufferedInputStream( zipInputStream );
177 		}
178 		else
179 		{
180 			String url = urlProperty.expand();
181 			inputStream = new BufferedInputStream( url == null ? new ByteArrayInputStream( new byte[0] )
182 					: new FileInputStream( url ) );
183 		}
184 
185 		AttachmentEncoding encoding = getEncoding();
186 		if( encoding == AttachmentEncoding.BASE64 )
187 		{
188 			ByteArrayOutputStream data = Tools.readAll( inputStream, Tools.READ_ALL );
189 			return new ByteArrayInputStream( Base64.encodeBase64( data.toByteArray() ) );
190 		}
191 		else if( encoding == AttachmentEncoding.HEX )
192 		{
193 			ByteArrayOutputStream data = Tools.readAll( inputStream, Tools.READ_ALL );
194 			return new ByteArrayInputStream( new String( Hex.encodeHex( data.toByteArray() ) ).getBytes() );
195 		}
196 
197 		return inputStream;
198 	}
199 
200 	public String getName()
201 	{
202 		return config.getName();
203 	}
204 
205 	public long getSize()
206 	{
207 		if( isCached() )
208 		{
209 			return config.getSize();
210 		}
211 		else
212 		{
213 			String url = urlProperty.expand();
214 			if( url != null )
215 			{
216 				File file = new File( url );
217 				if( file.exists() )
218 					return file.length();
219 			}
220 		}
221 
222 		return -1;
223 	}
224 
225 	public void release()
226 	{
227 		if( isCached() )
228 			new File( config.getTempFilename() ).delete();
229 	}
230 
231 	public String getPart()
232 	{
233 		return config.getPart();
234 	}
235 
236 	public void setContentType( String contentType )
237 	{
238 		config.setContentType( contentType );
239 	}
240 
241 	public void setPart( String part )
242 	{
243 		config.setPart( part );
244 	}
245 
246 	public void setData( byte[] data )
247 	{
248 		try
249 		{
250 			// write attachment-data to tempfile
251 			ByteArrayOutputStream tempData = new ByteArrayOutputStream();
252 			ZipOutputStream out = new ZipOutputStream( tempData );
253 			out.putNextEntry( new ZipEntry( config.getName() ) );
254 			config.setSize( data.length );
255 			out.write( data );
256 			out.closeEntry();
257 			out.finish();
258 			out.close();
259 			config.setData( tempData.toByteArray() );
260 		}
261 		catch( Exception e )
262 		{
263 			SoapUI.logError( e );
264 		}
265 	}
266 
267 	public byte[] getData() throws IOException
268 	{
269 		ByteArrayOutputStream out = new ByteArrayOutputStream();
270 		Tools.writeAll( out, getInputStream() );
271 		return out.toByteArray();
272 	}
273 
274 	public String getUrl()
275 	{
276 		return urlProperty.get();
277 	}
278 
279 	public boolean isCached()
280 	{
281 		return config.isSetData();
282 	}
283 
284 	abstract public AttachmentType getAttachmentType();
285 
286 	public void updateConfig( AttachmentConfig config )
287 	{
288 		this.config = config;
289 		urlProperty.setConfig( config );
290 	}
291 
292 	public AttachmentConfig getConfig()
293 	{
294 		return config;
295 	}
296 
297 	public void setContentID( String contentID )
298 	{
299 		if( ( contentID == null || contentID.length() == 0 ) && config.isSetContentId() )
300 			config.unsetContentId();
301 		else
302 			config.setContentId( contentID );
303 	}
304 
305 	public String getContentID()
306 	{
307 		return config.getContentId();
308 	}
309 
310 	public void resolve( ResolveContext<?> context )
311 	{
312 		if( isCached() )
313 			return;
314 
315 		urlProperty.resolveFile( context, "Missing attachment [" + getName() + "]", null, null, false );
316 	}
317 
318 	public String getContentEncoding()
319 	{
320 		AttachmentEncoding encoding = getEncoding();
321 		if( encoding == AttachmentEncoding.BASE64 )
322 			return "base64";
323 		else if( encoding == AttachmentEncoding.HEX )
324 			return "hex";
325 		else
326 			return "binary";
327 	}
328 }