United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4682039 : REGRESSION: Clipboard().setContents from JDK1.3.1 onwards does not work

Details
Type:
Bug
Submit Date:
2002-05-08
Status:
Closed
Updated Date:
2003-04-12
Project Name:
JDK
Resolved Date:
2002-08-08
Component:
client-libs
OS:
windows_2000
Sub-Component:
java.awt
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
1.4.2 (mantis)

Related Reports

Sub Tasks

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
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

======================================================================
                                     
2002-05-11
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
======================================================================
                                     
2002-05-24
PUBLIC COMMENTS

.
                                     
2004-09-17
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


                                     
2004-09-17



Hardware and Software, Engineered to Work Together