Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: 1.2, 1.2.1, 1.2.2
-
Fix Version/s: 1.3
-
Component/s: None
-
Labels:None
-
JDK version and platform:Java 1.6 Windows
Description
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
catch (Exception e)
}
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
catch (Exception e)
}
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
finally
{ oos.close(); } }
private static Settings readSettings(final String file) throws IOException, ClassNotFoundException
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
try
finally
{ ois.close(); } }
*/
}
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.