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.support.editor.inspectors.attachments;
14  
15  import java.awt.Component;
16  import java.awt.datatransfer.DataFlavor;
17  import java.awt.datatransfer.Transferable;
18  import java.awt.dnd.DnDConstants;
19  import java.awt.dnd.DropTarget;
20  import java.awt.dnd.DropTargetDragEvent;
21  import java.awt.dnd.DropTargetDropEvent;
22  import java.awt.dnd.DropTargetEvent;
23  import java.awt.dnd.DropTargetListener;
24  import java.awt.event.ActionEvent;
25  import java.awt.event.MouseAdapter;
26  import java.awt.event.MouseEvent;
27  import java.beans.PropertyChangeEvent;
28  import java.beans.PropertyChangeListener;
29  import java.io.File;
30  import java.io.FileNotFoundException;
31  import java.io.FileOutputStream;
32  import java.io.IOException;
33  import java.net.MalformedURLException;
34  import java.util.List;
35  
36  import javax.swing.AbstractListModel;
37  import javax.swing.ComboBoxModel;
38  import javax.swing.DefaultCellEditor;
39  import javax.swing.JButton;
40  import javax.swing.JComboBox;
41  import javax.swing.JFileChooser;
42  import javax.swing.JTable;
43  import javax.swing.event.ListSelectionEvent;
44  import javax.swing.event.ListSelectionListener;
45  
46  import com.eviware.soapui.SoapUI;
47  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
48  import com.eviware.soapui.impl.wsdl.AttachmentContainer;
49  import com.eviware.soapui.impl.wsdl.MutableAttachmentContainer;
50  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
51  import com.eviware.soapui.impl.wsdl.support.PathUtils;
52  import com.eviware.soapui.impl.wsdl.support.WsdlAttachment;
53  import com.eviware.soapui.model.iface.Attachment;
54  import com.eviware.soapui.model.iface.MessagePart.AttachmentPart;
55  import com.eviware.soapui.support.StringUtils;
56  import com.eviware.soapui.support.Tools;
57  import com.eviware.soapui.support.UISupport;
58  import com.eviware.soapui.support.components.JXToolBar;
59  
60  /***
61   * Utility Panel for displaying a table of attachments
62   * 
63   * @author emibre
64   */
65  
66  public class AttachmentsPanel extends javax.swing.JPanel
67  {
68  	private DropTarget dropTarget;
69  	private FileTransferHandler fileTransferHandler;
70  	private AttachmentsTableModel tableModel;
71  	private JFileChooser fc;
72  	private final AttachmentContainer container;
73  	private JButton exportBtn;
74  	private JButton reloadBtn;
75  
76  	/*** Creates new form FileTableList */
77  	public AttachmentsPanel( AttachmentContainer container )
78  	{
79  		this.container = container;
80  		initComponents();
81  		initFileTransfer();
82  	}
83  
84  	public void release()
85  	{
86  		tableModel.release();
87  		if( attachmentPartCellEditor != null )
88  			attachmentPartCellEditor.release();
89  	}
90  
91  	private void initFileTransfer()
92  	{
93  		if( container instanceof MutableAttachmentContainer )
94  		{
95  			fileTransferHandler = new FileTransferHandler( tableModel );
96  			fileTable.setDragEnabled( true );
97  			fileTable.setTransferHandler( fileTransferHandler );
98  
99  			dropTarget = new DropTarget();
100 			dropTarget.setActive( true );
101 			try
102 			{
103 				dropTarget.addDropTargetListener( new DropTargetListener()
104 				{
105 					public void dragEnter( DropTargetDragEvent dtde )
106 					{
107 					}
108 
109 					public void dragExit( DropTargetEvent dte )
110 					{
111 					}
112 
113 					public void dragOver( DropTargetDragEvent dtde )
114 					{
115 					}
116 
117 					@SuppressWarnings( "unchecked" )
118 					public void drop( DropTargetDropEvent dtde )
119 					{
120 						try
121 						{
122 							dtde.acceptDrop( DnDConstants.ACTION_COPY_OR_MOVE );
123 							Transferable trans = dtde.getTransferable();
124 							List<File> files = ( List<File> )trans.getTransferData( DataFlavor.javaFileListFlavor );
125 							for( File f : files )
126 							{
127 								System.out.println( "Dropping file: " + f.getName() );
128 
129 								Boolean retval = UISupport.confirmOrCancel( "Cache attachment in request?", "Att Attachment" );
130 								if( retval == null )
131 									return;
132 
133 								tableModel.addFile( f, retval );
134 							}
135 
136 						}
137 						catch( Exception e )
138 						{
139 							SoapUI.logError( e );
140 						}
141 					}
142 
143 					public void dropActionChanged( DropTargetDragEvent dtde )
144 					{
145 					}
146 				} );
147 			}
148 			catch( Exception e )
149 			{
150 				SoapUI.logError( e );
151 			}
152 
153 			jScrollPane1.getViewport().setDropTarget( dropTarget );
154 		}
155 	}
156 
157 	private void initComponents()
158 	{
159 		jScrollPane1 = new javax.swing.JScrollPane();
160 		tableModel = new AttachmentsTableModel( container );
161 		fileTable = new JTable( tableModel );
162 
163 		if( container instanceof MutableAttachmentContainer )
164 		{
165 			attachmentPartCellEditor = new AttachmentPartCellEditor();
166 			fileTable.getColumnModel().getColumn( 3 ).setCellEditor( attachmentPartCellEditor );
167 		}
168 
169 		setLayout( new java.awt.BorderLayout() );
170 		jScrollPane1.setViewportView( fileTable );
171 
172 		add( jScrollPane1, java.awt.BorderLayout.CENTER );
173 
174 		jPanel1 = UISupport.createSmallToolbar();
175 
176 		if( container instanceof MutableAttachmentContainer )
177 		{
178 			addFileBtn = UISupport.createToolbarButton( UISupport.createImageIcon( "/add_property.gif" ) );
179 			removeBtn = UISupport.createToolbarButton( UISupport.createImageIcon( "/remove_property.gif" ) );
180 			reloadBtn = UISupport.createToolbarButton( UISupport.createImageIcon( "/reload_properties.gif" ) );
181 
182 			addFileBtn.setToolTipText( "Adds an attachment" );
183 			addFileBtn.addActionListener( new java.awt.event.ActionListener()
184 			{
185 				public void actionPerformed( java.awt.event.ActionEvent evt )
186 				{
187 					addFileBtnActionPerformed( evt );
188 				}
189 			} );
190 
191 			jPanel1.addFixed( addFileBtn );
192 
193 			removeBtn.setToolTipText( "Removes the selected attachment" );
194 			removeBtn.setEnabled( false );
195 			removeBtn.addActionListener( new java.awt.event.ActionListener()
196 			{
197 				public void actionPerformed( java.awt.event.ActionEvent evt )
198 				{
199 					removeBtnActionPerformed( evt );
200 				}
201 			} );
202 
203 			jPanel1.addFixed( removeBtn );
204 
205 			reloadBtn.setToolTipText( "Reloads the selected attachment" );
206 			reloadBtn.setEnabled( false );
207 			reloadBtn.addActionListener( new java.awt.event.ActionListener()
208 			{
209 				public void actionPerformed( java.awt.event.ActionEvent evt )
210 				{
211 					reloadBtnActionPerformed( evt );
212 				}
213 			} );
214 
215 			jPanel1.addFixed( reloadBtn );
216 		}
217 
218 		exportBtn = UISupport.createToolbarButton( UISupport.createImageIcon( "/export.gif" ) );
219 		exportBtn.setToolTipText( "Exports the selected attachment to a file" );
220 		exportBtn.setEnabled( false );
221 		exportBtn.addActionListener( new java.awt.event.ActionListener()
222 		{
223 			public void actionPerformed( java.awt.event.ActionEvent evt )
224 			{
225 				exportBtnActionPerformed( evt );
226 			}
227 		} );
228 
229 		jPanel1.addFixed( exportBtn );
230 		jPanel1.addGlue();
231 		jPanel1.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.ATTACHMENTS_HELP_URL ) ) );
232 		add( jPanel1, java.awt.BorderLayout.NORTH );
233 
234 		fileTable.getSelectionModel().addListSelectionListener( new ListSelectionListener()
235 		{
236 			public void valueChanged( ListSelectionEvent e )
237 			{
238 				if( removeBtn != null )
239 				{
240 					removeBtn.setEnabled( fileTable.getSelectedRowCount() > 0 );
241 					reloadBtn.setEnabled( fileTable.getSelectedRowCount() > 0 );
242 				}
243 
244 				exportBtn.setEnabled( fileTable.getSelectedRowCount() > 0 );
245 			}
246 		} );
247 
248 		fileTable.addMouseListener( new MouseAdapter()
249 		{
250 			public void mouseClicked( MouseEvent e )
251 			{
252 				if( e.getClickCount() < 2 )
253 					return;
254 
255 				int ix = fileTable.getSelectedRow();
256 				if( ix == -1 )
257 					return;
258 
259 				Attachment attachment = container.getAttachmentAt( ix );
260 
261 				if( attachment.isCached() )
262 				{
263 					String name = attachment.getName();
264 					try
265 					{
266 						name = StringUtils.createFileName( name, '-' );
267 						File tempFile = File.createTempFile( "attachment-" + name.substring( 0, ix ), name.substring( ix ) );
268 						exportAttachment( tempFile, attachment, false );
269 					}
270 					catch( Exception e1 )
271 					{
272 						UISupport.showErrorMessage( e1 );
273 					}
274 				}
275 				else
276 				{
277 					Tools.openURL( attachment.getUrl() );
278 				}
279 			}
280 		} );
281 	}
282 
283 	protected void exportBtnActionPerformed( ActionEvent evt )
284 	{
285 		File file = UISupport.getFileDialogs().saveAs( this, "Export Attachment.." );
286 		while( file != null && file.exists()
287 				&& !UISupport.confirm( "File " + file.getName() + " exists, overwrite?", "Export Attachment" ) )
288 		{
289 			file = UISupport.getFileDialogs().saveAs( this, "Export Attachment.." );
290 		}
291 
292 		if( file != null )
293 		{
294 			Attachment attachment = tableModel.getAttachmentAt( fileTable.getSelectedRow() );
295 			try
296 			{
297 				exportAttachment( file, attachment, true );
298 			}
299 			catch( Exception e )
300 			{
301 				UISupport.showErrorMessage( e );
302 			}
303 		}
304 	}
305 
306 	private void exportAttachment( File file, Attachment attachment, boolean showOpenQuery )
307 			throws FileNotFoundException, IOException, Exception, MalformedURLException
308 	{
309 		FileOutputStream out = new FileOutputStream( file );
310 
311 		long total = Tools.writeAll( out, attachment.getInputStream() );
312 		out.close();
313 		if( !showOpenQuery
314 				|| UISupport.confirm( "Written [" + total + "] bytes to " + file.getName() + ", open in browser?",
315 						"Saved File" ) )
316 		{
317 			Tools.openURL( file.toURI().toURL().toString() );
318 		}
319 	}
320 
321 	protected void reloadBtnActionPerformed( ActionEvent evt )
322 	{
323 		int selectedRow = fileTable.getSelectedRow();
324 		if( selectedRow == -1 )
325 			return;
326 
327 		WsdlAttachment attachment = ( WsdlAttachment )tableModel.getAttachmentAt( selectedRow );
328 		if( attachment == null )
329 			return;
330 
331 		File file = UISupport.getFileDialogs().open( this, "Reload Attachment..", "*", "Any File", attachment.getUrl() );
332 		if( file != null )
333 		{
334 			Boolean retval = UISupport.confirmOrCancel( "Cache attachment in request?", "Reload Attachment" );
335 			if( retval == null )
336 				return;
337 
338 			try
339 			{
340 				attachment.reload( file, retval );
341 				tableModel.fireTableRowsUpdated( selectedRow, selectedRow );
342 			}
343 			catch( IOException e )
344 			{
345 				UISupport.showErrorMessage( e );
346 			}
347 		}
348 	}
349 
350 	private void addFileBtnActionPerformed( java.awt.event.ActionEvent evt )
351 	{// GEN-FIRST:event_addFileBtnActionPerformed
352 		if( fc == null )
353 			fc = new JFileChooser();
354 
355 		String root = PathUtils.getExpandedResourceRoot( container.getModelItem() );
356 		if( StringUtils.hasContent( root ) )
357 			fc.setCurrentDirectory( new File( root ) );
358 
359 		int returnVal = fc.showOpenDialog( this );
360 
361 		if( returnVal == JFileChooser.APPROVE_OPTION )
362 		{
363 			File file = fc.getSelectedFile();
364 			Boolean retval = UISupport.confirmOrCancel( "Cache attachment in request?", "Add Attachment" );
365 			if( retval == null )
366 				return;
367 			try
368 			{
369 				tableModel.addFile( file, retval );
370 			}
371 			catch( IOException e )
372 			{
373 				UISupport.showErrorMessage( e );
374 			}
375 		}
376 		else
377 		{
378 			System.out.println( "Open command cancelled by user." );
379 		}
380 	}// GEN-LAST:event_addFileBtnActionPerformed
381 
382 	private void removeBtnActionPerformed( java.awt.event.ActionEvent evt )
383 	{// GEN-FIRST:event_removeBtnActionPerformed
384 		if( UISupport.confirm( "Remove selected attachments?", "Remove Attachments" ) )
385 			tableModel.removeAttachment( fileTable.getSelectedRows() );
386 	}// GEN-LAST:event_removeBtnActionPerformed
387 
388 	// Variables declaration - do not modify//GEN-BEGIN:variables
389 	private javax.swing.JButton addFileBtn;
390 	private JTable fileTable;
391 	private JXToolBar jPanel1;
392 	private javax.swing.JScrollPane jScrollPane1;
393 	private javax.swing.JButton removeBtn;
394 	private AttachmentPartCellEditor attachmentPartCellEditor;
395 
396 	// End of variables declaration//GEN-END:variables
397 
398 	private class AttachmentPartCellEditor extends DefaultCellEditor
399 	{
400 		public AttachmentPartCellEditor()
401 		{
402 			super( new JComboBox( new PartsComboBoxModel() ) );
403 		}
404 
405 		public void release()
406 		{
407 			( ( PartsComboBoxModel )( ( JComboBox )editorComponent ).getModel() ).release();
408 		}
409 
410 		public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column )
411 		{
412 			PartsComboBoxModel model = ( ( PartsComboBoxModel )( ( JComboBox )editorComponent ).getModel() );
413 			( ( JComboBox )editorComponent ).setModel( model.init( tableModel.getAttachmentAt( row ) ) );
414 
415 			return super.getTableCellEditorComponent( table, value, isSelected, row, column );
416 		}
417 	}
418 
419 	private final class PartsComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener
420 	{
421 		private Attachment attachment;
422 		private AttachmentPart[] parts;
423 
424 		public PartsComboBoxModel()
425 		{
426 			container.addAttachmentsChangeListener( this );
427 		}
428 
429 		public void release()
430 		{
431 			container.removeAttachmentsChangeListener( this );
432 		}
433 
434 		public PartsComboBoxModel init( Attachment attachment )
435 		{
436 			this.attachment = attachment;
437 
438 			int previousPartsCount = parts == null ? 0 : parts.length;
439 
440 			parts = container.getDefinedAttachmentParts();
441 			if( previousPartsCount < parts.length )
442 			{
443 				fireIntervalAdded( this, previousPartsCount, parts.length );
444 			}
445 			else if( previousPartsCount > parts.length )
446 			{
447 				fireIntervalRemoved( this, parts.length - 1, previousPartsCount );
448 			}
449 
450 			fireContentsChanged( this, 0, parts.length - 1 );
451 
452 			return this;
453 		}
454 
455 		public Object getElementAt( int index )
456 		{
457 			return parts == null ? null : parts[index].getName();
458 		}
459 
460 		public int getSize()
461 		{
462 			return parts == null ? 0 : parts.length;
463 		}
464 
465 		public Object getSelectedItem()
466 		{
467 			return attachment == null ? null : attachment.getPart();
468 		}
469 
470 		public void setSelectedItem( Object anItem )
471 		{
472 			if( attachment != null )
473 				attachment.setPart( ( String )anItem );
474 		}
475 
476 		public void propertyChange( PropertyChangeEvent arg0 )
477 		{
478 			// delete our current one?
479 			if( arg0.getOldValue() == attachment && arg0.getNewValue() == null )
480 			{
481 				attachment = null;
482 				parts = null;
483 			}
484 		}
485 	}
486 }