1
2
3
4
5
6
7
8
9
10
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 {
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 }
381
382 private void removeBtnActionPerformed( java.awt.event.ActionEvent evt )
383 {
384 if( UISupport.confirm( "Remove selected attachments?", "Remove Attachments" ) )
385 tableModel.removeAttachment( fileTable.getSelectedRows() );
386 }
387
388
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
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
479 if( arg0.getOldValue() == attachment && arg0.getNewValue() == null )
480 {
481 attachment = null;
482 parts = null;
483 }
484 }
485 }
486 }