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 ) throws FileNotFoundException, IOException,
307 Exception, MalformedURLException
308 {
309 FileOutputStream out = new FileOutputStream( file );
310
311 long total = Tools.writeAll( out, attachment.getInputStream() );
312 out.close();
313 if( !showOpenQuery || UISupport.confirm( "Written [" + total + "] bytes to " + file.getName() + ", open in browser?", "Saved File" ))
314 {
315 Tools.openURL( file.toURI().toURL().toString() );
316 }
317 }
318
319 protected void reloadBtnActionPerformed( ActionEvent evt )
320 {
321 int selectedRow = fileTable.getSelectedRow();
322 if( selectedRow == -1 )
323 return;
324
325 WsdlAttachment attachment = (WsdlAttachment) tableModel.getAttachmentAt(selectedRow);
326 if( attachment == null )
327 return;
328
329 File file = UISupport.getFileDialogs().open( this, "Reload Attachment..", "*", "Any File", attachment.getUrl() );
330 if( file != null )
331 {
332 Boolean retval = UISupport.confirmOrCancel("Cache attachment in request?", "Reload Attachment");
333 if (retval == null)
334 return;
335
336 try
337 {
338 attachment.reload(file, retval);
339 tableModel.fireTableRowsUpdated(selectedRow, selectedRow);
340 }
341 catch (IOException e)
342 {
343 UISupport.showErrorMessage(e);
344 }
345 }
346 }
347
348
349 private void addFileBtnActionPerformed(java.awt.event.ActionEvent evt)
350 {
351 if (fc == null)
352 fc = new JFileChooser();
353
354 String root = PathUtils.getExpandedResourceRoot( container.getModelItem());
355 if( StringUtils.hasContent(root))
356 fc.setCurrentDirectory( new File(root));
357
358 int returnVal = fc.showOpenDialog(this);
359
360 if (returnVal == JFileChooser.APPROVE_OPTION)
361 {
362 File file = fc.getSelectedFile();
363 Boolean retval = UISupport.confirmOrCancel("Cache attachment in request?", "Add Attachment");
364 if (retval == null)
365 return;
366 try
367 {
368 tableModel.addFile(file, retval);
369 }
370 catch (IOException e)
371 {
372 UISupport.showErrorMessage(e);
373 }
374 }
375 else
376 {
377 System.out.println("Open command cancelled by user.");
378 }
379 }
380
381 private void removeBtnActionPerformed(java.awt.event.ActionEvent evt)
382 {
383 if (UISupport.confirm("Remove selected attachments?", "Remove Attachments"))
384 tableModel.removeAttachment(fileTable.getSelectedRows());
385 }
386
387
388 private javax.swing.JButton addFileBtn;
389 private JTable fileTable;
390 private JXToolBar jPanel1;
391 private javax.swing.JScrollPane jScrollPane1;
392 private javax.swing.JButton removeBtn;
393 private AttachmentPartCellEditor attachmentPartCellEditor;
394
395
396
397 private class AttachmentPartCellEditor extends DefaultCellEditor
398 {
399 public AttachmentPartCellEditor()
400 {
401 super(new JComboBox(new PartsComboBoxModel()));
402 }
403
404 public void release()
405 {
406 ((PartsComboBoxModel) ((JComboBox) editorComponent).getModel()).release();
407 }
408
409 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
410 {
411 PartsComboBoxModel model = ((PartsComboBoxModel) ((JComboBox) editorComponent).getModel());
412 ((JComboBox) editorComponent).setModel( model.init(tableModel.getAttachmentAt(row)) );
413
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 }