Is InputMap serializable or not?
Paulo Levi
i30817 at gmail.com
Tue Oct 21 18:04:02 UTC 2008
Hi. I found that the component input map advertises itself as
serializable, but it is really not, because somehow it seems to hold a
reference to a not serializable ActionMap.
A test case, sorry about the write/read functions, they were copied
from a utility class (as you can see i had to replace the logging
class):
package ui;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.InputMap;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import static junit.framework.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import util.io.IoUtils;
/**
*
* @author i30817
*/
public class ApplicationTest {
public ApplicationTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of read method, of class Application.
*/
@Test
public void testInputMapSerialization() {
JTextPane editor = new JTextPane();
InputMap map = editor.getInputMap();
KeyStroke keystroke = KeyStroke.getKeyStroke("shift SPACE");
map.put(keystroke, "test");
writeObjects("InputMap", map);
InputMap other = readObject("InputMap", new Callable(){
public Object call() throws Exception {
return new InputMap();
}
});
assertEquals("test", other.get(keystroke));
}
/**
* If possible reads an object, if not tries to instanciate the
* object with the given Callable. This allows lazy instantiation.
* This funtion can only read 1 object per file, to allow encapsulation
* of the inputstreams.
* If an exception occurs in the lazy instantiation it returns null.
* Remember that if using Externalizable transient fields/static scopes
* fields ARE initalized. The use of the default constructor assures that.
* The order of inicialization is:
* Externalizable : default constructor, readExternal
* Serializable : first non-serializable super class default constructor,
* readObject
* So with externalizable you need to be carefull to replace the super state
* and not to use it in the default constructor.
* In serializable, you need to replace the constructor state.
*/
@SuppressWarnings(value = "unchecked")
public static <T> T readObject(String objectLocation, Callable t) {
ObjectInputStream s = null;
try {
s = new ObjectInputStream(new BufferedInputStream(new
FileInputStream(objectLocation)));
return (T) s.readObject();
} catch (Throwable ex) {
Logger.getLogger(IoUtils.class.getName()).log(Level.WARNING,
"Couldnt read object", ex);
if (t != null) {
try {
return (T) t.call();
} catch (Throwable e) {
Logger.getLogger(ApplicationTest.class.getName()).log(Level.SEVERE,
"Couldnt create object", e);
}
}
} finally {
close(s);
}
return null;
}
/**
* If possible writes objects. Disallows null objects
*/
public static void writeObjects(String objectLocation,
Serializable... obj) {
ObjectOutputStream s = null;
try {
s = new ObjectOutputStream(new BufferedOutputStream(new
FileOutputStream(objectLocation)));
for (Serializable a : obj) {
if (a != null) {
s.writeObject(a);
}
}
s.flush();
} catch (Throwable ex) {
Logger.getLogger(ApplicationTest.class.getName()).log(Level.SEVERE,
"Couldnt write object", ex);
} finally {
close(s);
}
}
/**
* Close closeables. Use this in a finally clause.
*/
public static void close(Closeable... closeables) {
for (Closeable c : closeables) {
if (c != null) {
try {
c.close();
} catch (Throwable ex) {
Logger.getLogger(ApplicationTest.class.getName()).log(Level.WARNING,
"Couldnt close Closeable", ex);
}
}
}
}
}
More information about the core-libs-dev
mailing list