--- src/core/org/apache/jmeter/util/JMeterTreeNodeTransferable.java (revision 0) +++ src/core/org/apache/jmeter/util/JMeterTreeNodeTransferable.java (revision 0) @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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 { + + 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) { + ObjectInput ois = null; + try { + ois = new ObjectInputStream(new ByteArrayInputStream(data)); + JMeterTreeNode[] nodes = (JMeterTreeNode[]) ois.readObject(); + return nodes; + } catch (ClassNotFoundException cnfe) { + throw new IOException("Failed to read object stream.", cnfe); + } finally { + if(ois != null) { + try { + ois.close(); + } catch (Exception e) { + // NOOP + } + } + } + } + return null; + } + + public void setTransferData(JMeterTreeNode[] nodes) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = null; + try { + oos = new ObjectOutputStream(bos); + oos.writeObject(nodes); + data = bos.toByteArray(); + } finally { + if(oos != null) { + try { + oos.close(); + } catch (Exception e) { + // NOOP + } + } + } + } +} --- src/core/org/apache/jmeter/gui/action/Copy.java (revision 1392846) +++ src/core/org/apache/jmeter/gui/action/Copy.java (working copy) @@ -23,24 +23,27 @@ */ 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,26 +66,16 @@ } 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); - } - - public static JMeterTreeNode getCopiedNode() { - if (copiedNode == null) { - return null; - } - return cloneTreeNode(copiedNode); - } - - public static void setCopiedNode(JMeterTreeNode node) { - copiedNode = cloneTreeNode(node); + return null; } public static JMeterTreeNode cloneTreeNode(JMeterTreeNode node) { @@ -93,9 +86,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); } }