Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6708407

Using XMLEncoder To Write java.io.File Chosen From JFileChooser Fails

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 6
    • client-libs

      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.

            Unassigned Unassigned
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: