JDK-4682039 : REGRESSION: Clipboard().setContents from JDK1.3.1 onwards does not work
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-05-08
  • Updated: 2003-04-12
  • Resolved: 2002-08-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2 mantisFixed
Description

Name: gm110360			Date: 05/08/2002


FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

and

java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)


FULL OPERATING SYSTEM VERSION :

Microsoft Windows 2000 [5.00.2195]

A DESCRIPTION OF THE PROBLEM :
My application cut/copy/paste feature is failing when an
attempt is made to place a (Transferable) object on the
clipboard.  This used to work fine in 1.3, and began
failing when I upgraded to 1.4.


REGRESSION.  Last worked in version 1.3.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run my sample program in 1.3 - it works.
2. Run the same program in 1.4 - it gets an exception when
the clipboard's setContents method is called.


EXPECTED VERSUS ACTUAL BEHAVIOR :
The program should run in 1.4.



ERROR MESSAGES/STACK TRACES THAT OCCUR :
When I run my test case program in 1.4, I get the following Exception trace:

Exception in thread "main" java.lang.NullPointerException
        at sun.awt.datatransfer.DataTransferer.getFormatsForFlavors(DataTransfer
er.java:719)
        at sun.awt.windows.WDataTransferer.getFormatsForFlavors(WDataTransferer.
java:127)
        at sun.awt.datatransfer.DataTransferer.getFormatsForTransferable(DataTra
nsferer.java:687)
        at sun.awt.windows.WClipboard.setContents(WClipboard.java:63)
        at CBTest.main(CBTest.java:10)


In my application, the setContents method also fails, but gives a different
excetption trace:

java.lang.ClassCastException: java.lang.Object
	at sun.awt.datatransfer.DataTransferer.translateTransferable
(DataTransferer.java:1214)
	at sun.awt.windows.WDataTransferer.translateTransferable
(WDataTransferer.java:144)
	at sun.awt.windows.WClipboard.setContents(WClipboard.java:75)


This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.datatransfer.*;
import java.awt.*;
import javax.swing.*;

public class CBTest {

	public static void main(String[] args) {

		TransferableSample transferableSample = new TransferableSample
();
		Toolkit.getDefaultToolkit().getSystemClipboard().setContents
(transferableSample,transferableSample);
		System.out.println("Success");

  	}

static public class TransferableSample implements Transferable, ClipboardOwner {

	public DataFlavor imageFlavor;
	private DataFlavor [] supportedFlavors = {imageFlavor};
	private Image picture ;

	public TransferableSample () {

   		picture = new ImageIcon("wo.gif").getImage();

   	   	try {
   	    		imageFlavor = new DataFlavor (Class.forName
("java.awt.Image"), "Image");
        	}
       		catch (ClassNotFoundException e) {
   	    		e.printStackTrace ();
   	   	}

   	}
   
   	public synchronized DataFlavor [] getTransferDataFlavors () {
 
   		return (supportedFlavors);
   
   	}
   
   	public boolean isDataFlavorSupported (DataFlavor parFlavor) {
   
   		return (parFlavor.equals (imageFlavor));
   
   	}
   
   	public synchronized Object getTransferData (DataFlavor parFlavor)
   			   throws UnsupportedFlavorException {
   	   if (parFlavor.equals (imageFlavor))
   	    	return (picture);
   	   else
   	   	throw new UnsupportedFlavorException (imageFlavor);
   
   	 }
   
   	public void lostOwnership (Clipboard parClipboard, Transferable
parTransferable) {
   
        System.out.println ("Lost ownership");
	
	}
}
}
---------- END SOURCE ----------

Release Regression From : 1.3.0_05
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 146336) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis mantis-b02 FIXED IN: mantis mantis-b02 INTEGRATED IN: mantis mantis-b02 VERIFIED IN: mantis
17-09-2004

PUBLIC COMMENTS .
17-09-2004

SUGGESTED FIX Name: dsR10078 Date: 05/11/2002 Check for null elements when iterating over the supported data flavors. ###@###.### 2002-05-11 ====================================================================== Name: agR10216 Date: 05/24/2002 To protect our code from nulls, returned by Transferable.getTransferDataFlavors(), in addition to checking for null data flavors when iterating over them we should handle null DataFlavor array. --- DataTransferer.java Fri May 24 14:58:02 2002 *************** *** 667,673 **** */ public Map getFormatsForTransferable(Transferable contents, FlavorTable map) { ! return getFormatsForFlavors(contents.getTransferDataFlavors(), map); } /** --- 667,677 ---- */ public Map getFormatsForTransferable(Transferable contents, FlavorTable map) { ! DataFlavor[] flavors = contents.getTransferDataFlavors(); ! if (flavors == null) { ! return new HashMap(0); ! } ! return getFormatsForFlavors(flavors, map); } /** *************** *** 686,691 **** --- 690,700 ---- * in the specified DataFlavors can be translated. The value of each key * is the DataFlavor in which the Transferable's data should be requested * when converting to the format. + * + * @param flavors the data flavors + * @param map the FlavorTable which contains mappings between + * DataFlavors and data formats + * @throws NullPointerException if flavors or map is <code>null</code> */ public Map getFormatsForFlavors(DataFlavor[] flavors, FlavorTable map) { Map formatMap = new HashMap(flavors.length); *************** *** 696,701 **** --- 705,711 ---- // Transferable.getTransferDataFlavors.) for (int i = flavors.length - 1; i >= 0; i--) { DataFlavor flavor = flavors[i]; + if (flavor == null) continue; // Don't explicitly test for String, since it is just a special // case of Serializable ###@###.### 2002-05-24 ======================================================================
24-05-2002

EVALUATION Name: dsR10078 Date: 05/11/2002 The NullPointerException is thrown because the imageFlavor field is initialized after the supportedFlavors field. As a result the supportedFlavors references an array that contains a null element. This exception didn't manifest in 1.3 on Windows, because transfer of non-textual data via the clipboard was not supported. In 1.4 the clipboard support was enchanced, so that it is possible to transfer data in various formats. The data transfer subsystem iterates over the data flavors supported by the specified Transferable and operates on them without check for null. Strictly, the TransferableSample is incorrect, as isDataFlavorSupported() returns true for the a non-null imageFlavor, while getTransferDataFlavors() returns an array that contains a single null element. The test should be modified as follows: ------------------------------------------------------------------------ --- CBTest.java Sat May 11 14:15:41 2002 *************** *** 17,23 **** static public class TransferableSample implements Transferable, ClipboardOwner { public DataFlavor imageFlavor; ! private DataFlavor [] supportedFlavors = {imageFlavor}; private Image picture ; public TransferableSample () { --- 17,23 ---- static public class TransferableSample implements Transferable, ClipboardOwner { public DataFlavor imageFlavor; ! private DataFlavor [] supportedFlavors; private Image picture ; public TransferableSample () { *************** *** 31,36 **** --- 31,38 ---- catch (ClassNotFoundException e) { e.printStackTrace (); } + + supportedFlavors = new DataFlavor[] {imageFlavor}; } public synchronized DataFlavor [] getTransferDataFlavors () { ------------------------------------------------------------------------ When the test is modified in this way, the exception is no longer thrown. This test exposes a bug in the data transfer subsystem, since the javadoc doesn't specify that Clipboard.setContents() throws NPE when an array returned from the Transferable.getTransferDataFlavors() contains a null element. ###@###.### 2002-05-11 ====================================================================== Name: dsR10078 Date: 05/11/2002 With JDK 1.3, the test completes without an exception on Windows, but on Solaris the test fails with exception: <das@horror(pts/17).406> /set/java/jdk1.3/solaris/bin/java -version java version "1.3.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C) Java HotSpot(TM) Client VM (build 1.3.0-C, interpreted mode) <das@horror(pts/17).407> /set/java/jdk1.3/solaris/bin/java CBTest Exception in thread "main" java.lang.NullPointerException at sun.awt.motif.X11Selection.putDataInAllFlavors(X11Selection.java:177) at sun.awt.motif.X11Selection.getSelectionOwnership(X11Selection.java:201) at sun.awt.motif.X11Clipboard.setContents(X11Clipboard.java:41) at CBTest.main(CBTest.java:11) ###@###.### 2002-05-11 ======================================================================
11-05-2002