Index: src/core/org/apache/jmeter/gui/action/Copy.java =================================================================== --- src/core/org/apache/jmeter/gui/action/Copy.java (revision 1197485) +++ src/core/org/apache/jmeter/gui/action/Copy.java (working copy) @@ -23,24 +23,29 @@ */ package org.apache.jmeter.gui.action; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; import java.awt.event.ActionEvent; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; +import javax.swing.JOptionPane; + import org.apache.jmeter.gui.GuiPackage; import org.apache.jmeter.gui.tree.JMeterTreeListener; import org.apache.jmeter.gui.tree.JMeterTreeNode; import org.apache.jmeter.testelement.TestElement; +import org.apache.jmeter.util.JMeterTreeNodeTransferable; +import org.apache.jmeter.util.JMeterUtils; /** * Implements the Copy menu command */ public class Copy extends AbstractAction { + private static JMeterTreeNode copiedNode = null; - private static JMeterTreeNode copiedNodes[] = null; - private static final HashSet commands = new HashSet(); static { @@ -63,15 +68,15 @@ } public static JMeterTreeNode[] getCopiedNodes() { - if (copiedNodes == null) { // can be null if Copy has yet to be used - return null; - } - for (int i = 0; i < copiedNodes.length; i++) { - if (copiedNodes[i] == null) { - return null; + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + if(clipboard.isDataFlavorAvailable(JMeterTreeNodeTransferable.JMETER_TREE_NODE_ARRAY_DATA_FLAVOR)) { + try { + return (JMeterTreeNode[]) clipboard.getData(JMeterTreeNodeTransferable.JMETER_TREE_NODE_ARRAY_DATA_FLAVOR); + } catch (Exception ex) { + JOptionPane.showMessageDialog(GuiPackage.getInstance().getMainFrame(), JMeterUtils.getResString("clipboard_node_read_error")+":\n" + ex.getLocalizedMessage(), JMeterUtils.getResString("error_title"), JOptionPane.ERROR_MESSAGE); } } - return cloneTreeNodes(copiedNodes); + return null; } public static JMeterTreeNode getCopiedNode() { @@ -93,9 +98,13 @@ } public static void setCopiedNodes(JMeterTreeNode nodes[]) { - copiedNodes = new JMeterTreeNode[nodes.length]; - for (int i = 0; i < nodes.length; i++) { - copiedNodes[i] = cloneTreeNode(nodes[i]); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + try { + JMeterTreeNodeTransferable transferable = new JMeterTreeNodeTransferable(); + transferable.setTransferData(nodes); + clipboard.setContents(transferable, null); + } catch (Exception ex) { + JOptionPane.showMessageDialog(GuiPackage.getInstance().getMainFrame(), JMeterUtils.getResString("clipboard_node_read_error")+":\n" + ex.getLocalizedMessage(), JMeterUtils.getResString("error_title"), JOptionPane.ERROR_MESSAGE); } } Index: src/core/org/apache/jmeter/resources/messages.properties =================================================================== --- src/core/org/apache/jmeter/resources/messages.properties (revision 1197485) +++ src/core/org/apache/jmeter/resources/messages.properties (working copy) @@ -125,6 +125,8 @@ clear_all=Clear All clear_cache_per_iter=Clear cache each iteration? clear_cookies_per_iter=Clear cookies each iteration? +clipboard_node_read_error=Error retrieving nodes from clipboard +clipboard_node_write_error=Error coping nodes to clipboard column_delete_disallowed=Deleting this column is not permitted column_number=Column number of CSV file | next | *alias compare=Compare Index: src/core/org/apache/jmeter/util/JMeterTreeNodeTransferable.java =================================================================== --- src/core/org/apache/jmeter/util/JMeterTreeNodeTransferable.java (revision 0) +++ src/core/org/apache/jmeter/util/JMeterTreeNodeTransferable.java (revision 0) @@ -0,0 +1,68 @@ +package org.apache.jmeter.util; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.apache.jmeter.gui.tree.JMeterTreeNode; + +/** + * Simple implementation of a transferable for {@link JMeterTreeNode} arrays based on serialization. + */ +public class JMeterTreeNodeTransferable implements Transferable { + + private static final long serialVersionUID = 192L; + + public final static DataFlavor JMETER_TREE_NODE_ARRAY_DATA_FLAVOR = new DataFlavor(JMeterTreeNode[].class, JMeterTreeNode[].class.getName()); + + private final static DataFlavor[] DATA_FLAVORS = new DataFlavor[]{JMETER_TREE_NODE_ARRAY_DATA_FLAVOR}; + + private byte[] data = null; + + @Override + public DataFlavor[] getTransferDataFlavors() { + return DATA_FLAVORS; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.match(JMETER_TREE_NODE_ARRAY_DATA_FLAVOR); + } + + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if(!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + if(data != null) { + ByteArrayInputStream bis = new ByteArrayInputStream(data); + ObjectInput ois = new ObjectInputStream(bis); + try { + JMeterTreeNode[] nodes = (JMeterTreeNode[]) ois.readObject(); + return nodes; + } catch (ClassNotFoundException cnfe) { + throw new IOException("Failed to read object stream.", cnfe); + } finally { + ois.close(); + bis.close(); + } + } + return null; + } + + public void setTransferData(JMeterTreeNode[] nodes) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(nodes); + oos.close(); + bos.close(); + data = bos.toByteArray(); + } + +}