History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: XSTR-426
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Joerg Schaible
Reporter: Jurgen Voorneveld
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
XStream

KeyStroke not working as accelerator after being deserialized

Created: 10/Sep/07 04:26 AM   Updated: 25/Feb/08 05:01 PM
Component/s: None
Affects Version/s: 1.2, 1.2.1, 1.2.2
Fix Version/s: 1.3

File Attachments: 1. Text File xstr-426-testcode.patch (5 kb)


JDK version and platform: Java 1.6 Windows


 Description  « Hide
I ran into a bug when using xstream. Even though KeyStroke is succesfully written to file and read from file it cannot be used anymore. I've attached example code that demonstrates the problem. If you use ObjectOuputStream and ObjectInputStream for serializing everything is fine and the Foo alert is shown when you press B. If you use xstream the alert is not shown.

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public final class FrameMain extends JFrame implements WindowListener
{
  private JPanel main = new JPanel();
  
  public static void main(String[] args)
  {
    new FrameMain();
  }
  
  public FrameMain()
  {
    super.setTitle("Xstream KeyStroke bug");
    super.setLocation(300, 300);
    super.setSize(200, 200);
    super.addWindowListener(this);

    JButton button = new JButton("Foo");
    button.setAction(new ActionFoo(this));
    this.main.add(button);
    
    KeyStroke key = null;
    //key = KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK, true);
    key = Settings.getInstance().getAcceleratorMap().get(ActionFoo.class);
    System.out.println(key);
    
    this.main.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, ActionFoo.class.getSimpleName());
    this.main.getActionMap().put(ActionFoo.class.getSimpleName(), new ActionFoo(this));
   
    super.setContentPane(this.main);
    super.setVisible(true);
  }
  
  public void windowClosing(final WindowEvent event)
  {
    Settings.getInstance().writeSettings();
    System.exit(0);
  }
  public void windowIconified(final WindowEvent event)
  { /* nothing */ }
  public void windowOpened(final WindowEvent event)
  { /* nothing */ }
  public void windowClosed(final WindowEvent event)
  { /* nothing */ }
  public void windowDeiconified(final WindowEvent event)
  { /* nothing */ }
  public void windowActivated(final WindowEvent event)
  { /* nothing */ }
  public void windowDeactivated(final WindowEvent event)
  { /* nothing */ }
}

import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JOptionPane;

final class ActionFoo extends AbstractAction
{
  private FrameMain parent;
  
  public ActionFoo(FrameMain parent)
  {
    this.parent = parent;
  }
  
  public void actionPerformed(ActionEvent arg0)
  {
    JOptionPane.showMessageDialog(this.parent, "Foo");
  }
}

import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;

import javax.swing.KeyStroke;

import com.thoughtworks.xstream.XStream;

final class Settings implements Serializable
{
  private static Settings instance = null;

  private HashMap<Class<?>, KeyStroke> acceleratorMap = null;
  
  public static Settings getInstance()
  {
    if (instance == null)
    {
      try {
        instance = readSettings("settings.obj"); //$NON-NLS-1$
      }
      catch (Exception e) {
        e.printStackTrace();
        instance = new Settings();
      }
    }
    return instance;
  }
  
  private Settings()
  {
    this.setDefaultAccelerators();
  }
  
  /**
   * Sets the default accelerators for each action used in this program.
   */
  public void setDefaultAccelerators()
  {
    if (this.acceleratorMap == null)
      this.acceleratorMap = new HashMap<Class<?>, KeyStroke>();
    else
      this.acceleratorMap.clear();
    
    this.acceleratorMap.put(ActionFoo.class, KeyStroke.getKeyStroke(KeyEvent.VK_B, 0, true));
  }

  public void writeSettings()
  {
    try {
      this.write("settings.obj"); //$NON-NLS-1$
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  public HashMap<Class<?>, KeyStroke> getAcceleratorMap()
  {
    return this.acceleratorMap;
  }

  private final void write(final String file) throws IOException
  {
    XStream xstream = new XStream();
    xstream.toXML(this, new FileOutputStream(file));
  }
  public static Settings readSettings(final String file) throws IOException
  {
    XStream xstream = new XStream();
    return (Settings) xstream.fromXML(new FileInputStream(file));
  }
  /*
  private final void write(final String file) throws IOException
  {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
    try {
      oos.writeObject(this);
    }
    finally {
      oos.close();
    }
  }
  private static Settings readSettings(final String file) throws IOException, ClassNotFoundException
  {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
    try {
      return (Settings) ois.readObject();
    }
    finally {
      ois.close();
    }
  }
  */
}


 All   Comments   Change History      Sort Order: Ascending order - Click to sort in descending order
Joerg Schaible - 24/Sep/07 02:52 PM
Fixed in head revision. Issue was caused by a '\uffff' character that was stored in the KeyStroke. This could not be handled by the PrettyPrintWriter. Characters not defined in unicode are now written as numeric entity.

Joerg Schaible - 25/Feb/08 05:01 PM
Closing issues before next release.