JDK-6708407 : Using XMLEncoder To Write java.io.File Chosen From JFileChooser Fails
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 6
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: linux
  • CPU: x86
  • Submitted: 2008-05-29
  • Updated: 2021-07-13
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
tbdUnresolved
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Linux coco-laptop 2.6.20-16-generic #2 SMP Sun Sep 23 19:50:39 UTC 2007 i686 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
java.io.File has no PersistenceDelegate. Creating a simple one and saving a File directly works normally.

When choosing a File with a JFileChooser, saving this fails; mentioning:

java.lang.InstantiationException: sun.awt.shell.DefaultShellFolder

I do not know the exact location of the failure in code. A test case is given.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a simple File PersistenceDelegate. Verify that saving a file works. Then choose a file from a JFileChooser and try saving that one: this will fail.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
Two cases; both have the same PersistenceDelegate set for java.io.File:

When saving a File:

java.lang.InstantiationException: sun.awt.shell.DefaultShellFolder
Continuing ...
java.lang.Exception: XMLEncoder: discarding statement XMLEncoder.writeObject(DefaultShellFolder);
Continuing ...


When saving a JavaBean that has a read/write property of type File:

java.lang.InstantiationException: sun.awt.shell.DefaultShellFolder
Continuing ...
java.lang.RuntimeException: failed to evaluate: <unbound>=Class.new();
Continuing ...



REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.XMLEncoder;
import java.io.File;
import java.io.FileOutputStream;
import javax.swing.JFileChooser;
import java.beans.Encoder;
import java.beans.Expression;
import java.beans.PersistenceDelegate;
import java.io.IOException;
import java.net.URI;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingWorker;

public class FilePersistTest2 {
    
    /** Executes 2 XMLEncoder writeObject attempts: one for a File, and one for a FilePersistTest2 bean. */
    public static class MyWorker extends SwingWorker<Void, Void> {
        
        private final File file;
        
        public MyWorker(final File file) {
            this.file = file;
        }
        
        @Override protected Void doInBackground() throws Exception {
            Thread.yield();
            System.out.println();
            System.out.println();
            System.out.println();
            System.out.println("Saving File: " + file);
            save(file);

            final FilePersistTest2 filePersistTest2 = new FilePersistTest2();
            filePersistTest2.setFile(file);
            System.out.println();
            System.out.println("Saving JavaBean: " + filePersistTest2);
            save(filePersistTest2);
            
            return null;
        }
        
    }
    
    
    private static final PersistenceDelegate filePersistenceDelegate = new PersistenceDelegate() {
        @Override
        protected Expression instantiate(final Object oldInstance, final Encoder out) {
            return new Expression(oldInstance, File.class, "new", new URI[] { ((File) oldInstance).toURI() });
        }
    };
    private static final File staticFile = new File(System.getProperty("user.home"));
    private static Class<?> shellFolderClass;
    
    
    /** Executes 6 XMLEncoder writeObject attempts: the last 2 fail. */
    public static void main(final String[] args) throws Exception {
        try {
            shellFolderClass = Class.forName("sun.awt.shell.DefaultShellFolder");
        } catch (final ClassNotFoundException cnfEx) {
            System.out.println("Can't get Class for sun.awt.shell.DefaultShellFolder.");
            cnfEx.printStackTrace();
            System.exit(1);
        }
        
        // Save the static file: this works:
        (new MyWorker(staticFile)).execute();
        
        // Open a file chooser and then save THE CHOSEN FILE: this does not work:
        // Two different errors are produced: one when saving the File directly,
        // And one when saving a Bean with a File property:
        // Save the static file still works:
        final JFrame frame = new JFrame("FilePersistTest2");
        final JButton button = new JButton("Choose File...");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                final JFileChooser chooser = new JFileChooser();
                if (chooser.showOpenDialog(frame) != JFileChooser.APPROVE_OPTION) return;
                (new MyWorker(staticFile)).execute();
                (new MyWorker(chooser.getSelectedFile())).execute();
                // The workaround is this: create a new file:
//                (new MyWorker(new File(chooser.getSelectedFile().getPath()))).execute();
            }
        });
        frame.add(button);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    /** Each save sets the PersistenceDelegate for java.io.File to the static field in this class. */
    private static void save(final Object object) {
        XMLEncoder encoder = null;
        PersistenceDelegate initialFileDelegate = null;
        try {
            final File tempFile = File.createTempFile("FilePersistTest2", ".xml");
            tempFile.deleteOnExit();
            encoder = new XMLEncoder(new FileOutputStream(tempFile));
            initialFileDelegate = encoder.getPersistenceDelegate(File.class);
            System.out.println("Initial PersistenceDelegate for java.io.File: " + initialFileDelegate);
            System.out.println(
                    "Initial PersistenceDelegate for sun.awt.shell.DefaultShellFolder: "
                            + encoder.getPersistenceDelegate(shellFolderClass));
            encoder.setPersistenceDelegate(File.class, filePersistenceDelegate);
            encoder.writeObject(object);
        } catch (final IOException ioEx) {
            System.out.println("Caught IOException while saving object.");
            ioEx.printStackTrace();
        } finally {
            if (encoder != null) {
                encoder.close();
                System.out.println(
                        "Final PersistenceDelegate for java.io.File: "
                                + encoder.getPersistenceDelegate(File.class));
                System.out.println(
                        "Final PersistenceDelegate for sun.awt.shell.DefaultShellFolder: "
                                + encoder.getPersistenceDelegate(shellFolderClass));
                encoder.setPersistenceDelegate(File.class, initialFileDelegate);
            }
        }
    }
    
    
    private File file;
    
    public File getFile() { return file; }
    
    public void setFile(final File file) { this.file = file; }
    
    @Override public String toString() { return super.toString() + " [file=" + file + "]"; }
    
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Instead of saving the CHOSEN File, make a new file using that File's path, and save that one. The instance returned by JFileChooser must be a subclass.

Comments
EVALUATION JFileChooser should return instance of the File class as user expected.
29-05-2008