# HG changeset patch # User Jaroslav Tulach # Date 1233502061 -3600 # Node ID cb8db49f9d1c520366410dbb3b549f4d5e2634ac # Parent fba31e9504a15a5c3f2568ef374bf2cfec7a25d1 Rearranged to support test as well as interactive modes diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/IOManager.java --- a/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/IOManager.java Sun Feb 01 16:03:37 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package org.apidesign.exceptions.trycatchredo; - -import java.net.URL; -import javax.swing.Action; - -/** - * - * @author Jaroslav Tulach - */ -public final class IOManager { - static boolean old; - - IOManager() { - } - - /** Action that can store a text to given URL. - * - * @param where the url to upload the text to - * @param what the text to upload - * @return action that can be invoked anytime to save the content - */ - public static Action createSaveAction(URL where, CharSequence what) { - if (old) { - return new SaveAction(where, what); - } else { - return new SaveActionWithQuery(where, what); - } - } -} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/SaveAction.java --- a/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/SaveAction.java Sun Feb 01 16:03:37 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -package org.apidesign.exceptions.trycatchredo; - -import java.awt.EventQueue; -import java.awt.event.ActionEvent; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URL; -import javax.swing.AbstractAction; -import javax.swing.JOptionPane; - -/** - * - * @author Jaroslav Tulach - */ -final class SaveAction extends AbstractAction { - private final URL where; - private final CharSequence what; - - SaveAction(URL where, CharSequence what) { - this.where = where; - this.what = what; - } - - - public void actionPerformed(ActionEvent ev) { - assert EventQueue.isDispatchThread(); - try { - OutputStream os = where.openConnection().getOutputStream(); - os.write(what.toString().getBytes()); - os.close(); - } catch (IOException ex) { - JOptionPane.showMessageDialog(null, ex); - } - } -} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/SaveActionWithQuery.java --- a/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/SaveActionWithQuery.java Sun Feb 01 16:03:37 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package org.apidesign.exceptions.trycatchredo; - -import java.awt.EventQueue; -import java.awt.event.ActionEvent; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URL; -import javax.swing.AbstractAction; -import javax.swing.JDialog; -import javax.swing.JOptionPane; - -/** - * - * @author Jaroslav Tulach - */ -final class SaveActionWithQuery extends AbstractAction { - private final URL where; - private final CharSequence what; - - SaveActionWithQuery(URL where, CharSequence what) { - this.where = where; - this.what = what; - } - - - public void actionPerformed(ActionEvent ev) { - assert EventQueue.isDispatchThread(); - for (;;) { - try { - OutputStream os = where.openConnection().getOutputStream(); - os.write(what.toString().getBytes()); - os.close(); - } catch (UserQuestionException ex) { - JOptionPane p = ex.getQuestionPane(); - JDialog d = p.createDialog(ex.getLocalizedMessage()); - d.setVisible(true); - ex.confirm(p.getValue()); - if ( - !p.getValue().equals(JOptionPane.CANCEL_OPTION) && - !p.getValue().equals(JOptionPane.CLOSED_OPTION) - ) { - continue; - } - } catch (IOException ex) { - JOptionPane.showMessageDialog(null, ex); - } - break; - } - } -} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/UserQuestionException.java --- a/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/UserQuestionException.java Sun Feb 01 16:03:37 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package org.apidesign.exceptions.trycatchredo; - -import java.io.IOException; -import javax.swing.JOptionPane; - -/** Specialized I/O exception to request some kind of user confirmation. - * A code that needs to ask user shall not attempt to open a dialog itself, - * rather it shall emit this exception and let its callers show the dialog - * at appropriate time. - * - * @author Jaroslav Tulach - * @since 2.0 - */ -public abstract class UserQuestionException extends IOException { - /** Description of the dialog to show to the user. Whoever catches - * this exception shall use {@link #getQuestionPane()}.{@link JOptionPane#createDialog(java.lang.String)} - * to construct and display the dialog. - * - * @return the pane to display to user - */ - public abstract JOptionPane getQuestionPane(); - /** When the user confirms (or rejects) message presented by the - * {@link #getQuestionPane()} dialog, the exception shall be notified - * by calling this method with {@link JOptionPane#getValue()} option. - * - * @param option the option selected by the user - */ - public abstract void confirm(Object option); -} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/IOManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/IOManager.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,44 @@ +package org.apidesign.exceptions.trycatchredo.api; + +import java.net.URL; +import javax.swing.Action; +import javax.swing.JDialog; +import javax.swing.JOptionPane; + +/** + * + * @author Jaroslav Tulach + */ +public final class IOManager { + IOManager() { + } + + /** Action that can store a text to given URL. + * + * @param where the url to upload the text to + * @param what the text to upload + * @return action that can be invoked anytime to save the content + */ + public static Action createSaveAction(URL where, CharSequence what) { + if (old) { + return new SaveAction(where, what); + } else { + return new SaveActionWithQuery(where, what); + } + } + + // + // Support for executing mock objects in tests + // + + static boolean old; + static Object setVisibleOption; + static void setVisible(JDialog d, JOptionPane p) { + if (setVisibleOption == null) { + d.setVisible(true); + } else { + // only in test mode + p.setValue(setVisibleOption); + } + } +} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/SaveAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/SaveAction.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,35 @@ +package org.apidesign.exceptions.trycatchredo.api; + +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; + +/** + * + * @author Jaroslav Tulach + */ +final class SaveAction extends AbstractAction { + private final URL where; + private final CharSequence what; + + SaveAction(URL where, CharSequence what) { + this.where = where; + this.what = what; + } + + + public void actionPerformed(ActionEvent ev) { + assert EventQueue.isDispatchThread(); + try { + OutputStream os = where.openConnection().getOutputStream(); + os.write(what.toString().getBytes()); + os.close(); + } catch (IOException ex) { + JOptionPane.showMessageDialog(null, ex); + } + } +} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/SaveActionWithQuery.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/SaveActionWithQuery.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,54 @@ +package org.apidesign.exceptions.trycatchredo.api; + +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import javax.swing.AbstractAction; +import javax.swing.JDialog; +import javax.swing.JOptionPane; + +/** + * + * @author Jaroslav Tulach + */ +final class SaveActionWithQuery extends AbstractAction { + private final URL where; + private final CharSequence what; + + SaveActionWithQuery(URL where, CharSequence what) { + this.where = where; + this.what = what; + } + + + public void actionPerformed(ActionEvent ev) { + assert EventQueue.isDispatchThread(); + for (;;) { + try { + OutputStream os = where.openConnection().getOutputStream(); + os.write(what.toString().getBytes()); + os.close(); + } catch (UserQuestionException ex) { + JOptionPane p = ex.getQuestionPane(); + JDialog d = p.createDialog(ex.getLocalizedMessage()); + setVisible(d, p); + ex.confirm(p.getValue()); + if ( + !p.getValue().equals(JOptionPane.CANCEL_OPTION) && + !p.getValue().equals(JOptionPane.CLOSED_OPTION) + ) { + continue; + } + } catch (IOException ex) { + JOptionPane.showMessageDialog(null, ex); + } + break; + } + } + + private static void setVisible(JDialog d, JOptionPane p) { + IOManager.setVisible(d, p); + } +} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/UserQuestionException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/api/UserQuestionException.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,29 @@ +package org.apidesign.exceptions.trycatchredo.api; + +import java.io.IOException; +import javax.swing.JOptionPane; + +/** Specialized I/O exception to request some kind of user confirmation. + * A code that needs to ask user shall not attempt to open a dialog itself, + * rather it shall emit this exception and let its callers show the dialog + * at appropriate time. + * + * @author Jaroslav Tulach + * @since 2.0 + */ +public abstract class UserQuestionException extends IOException { + /** Description of the dialog to show to the user. Whoever catches + * this exception shall use {@link #getQuestionPane()}.{@link JOptionPane#createDialog(java.lang.String)} + * to construct and display the dialog. + * + * @return the pane to display to user + */ + public abstract JOptionPane getQuestionPane(); + /** When the user confirms (or rejects) message presented by the + * {@link #getQuestionPane()} dialog, the exception shall be notified + * by calling this method with {@link JOptionPane#getValue()} option. + * + * @param option the option selected by the user + */ + public abstract void confirm(Object option); +} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/usage/Main.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/usage/Main.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,35 @@ +package org.apidesign.exceptions.trycatchredo.usage; + +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.net.URL; +import javax.swing.Action; +import org.apidesign.exceptions.trycatchredo.api.IOManager; +import org.apidesign.exceptions.trycatchredo.api.UserQuestionException; + +/** Sample usage showing interactive storage capabilities of the + * {@link UserQuestionException} + * + * @author Jaroslav Tulach + */ +public class Main { + public static void main(String[] args) throws Exception { + MemoryURL.initialize(); + + for (int cnt = 0; cnt < 10; cnt++) { + URL u = new URL("memory://" + cnt + "/queryEncoding.txt"); + MemoryURL.registerURL(u.toExternalForm(), "", new QueryStream()); + final Action a = IOManager.createSaveAction(u, "Ask a Question"); + EventQueue.invokeAndWait(new Runnable() { + public void run() { + a.actionPerformed(new ActionEvent(this, 0, "")); + } + }); + String out = MemoryURL.getOutputForURL(u.toExternalForm()); + + System.err.println(cnt + " output: " + out); + } + + System.exit(0); + } +} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/usage/MemoryURL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/usage/MemoryURL.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,94 @@ + +package org.apidesign.exceptions.trycatchredo.usage; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.util.HashMap; +import java.util.Map; + +/** Support for special "memory://" URLs. Useful when testing network communication. + * + * @author Jaroslav Tulach + */ +public final class MemoryURL extends URLStreamHandler { + private MemoryURL() { + } + + public static void initialize() { + } + static { + class F implements URLStreamHandlerFactory { + public URLStreamHandler createURLStreamHandler(String protocol) { + if (protocol.startsWith("memory")) { + return new MemoryURL(); + } + return null; + } + } + F f = new F(); + URL.setURLStreamHandlerFactory(f); + } + + private static Map contents = new HashMap(); + private static Map outputs = new HashMap(); + + public static void registerURL(String u, String content, OutputStream out) throws MalformedURLException { + contents.put(u, new ByteArrayInputStream(content.getBytes())); + outputs.put(u, out); + } + + public static String getOutputForURL(String u) { + OutputStream out = outputs.get(u); + return out.toString(); + } + + protected URLConnection openConnection(URL u) throws IOException { + return new MC(u); + } + + private static final class MC extends URLConnection { + private InputStream values; + private OutputStream out; + + public MC(URL u) { + super(u); + out = outputs.get(u.toExternalForm()); + if (out == null) { + out = new ByteArrayOutputStream(); + outputs.put(u.toExternalForm(), out); + } + } + + public void connect() throws IOException { + if (values != null) { + return; + } + values = contents.remove(url.toExternalForm()); + if (values == null) { + throw new IOException("No such content: " + url); + } + } + + @Override + public InputStream getInputStream() throws IOException { + connect(); + return values; + } + + @Override + public OutputStream getOutputStream() throws IOException { + if (out == null) { + out = new ByteArrayOutputStream(); + } + return out; + } + } +} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/src/org/apidesign/exceptions/trycatchredo/usage/QueryStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/src/org/apidesign/exceptions/trycatchredo/usage/QueryStream.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,65 @@ +package org.apidesign.exceptions.trycatchredo.usage; + +import org.apidesign.exceptions.trycatchredo.api.UserQuestionException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.swing.JOptionPane; + +public final class QueryStream extends OutputStream { + private ByteArrayOutputStream arr = new ByteArrayOutputStream(); + /** this field can be manipulated by the QueryException */ + Boolean reverse; + + @Override + public synchronized void write(byte[] b, int off, int len) throws IOException { + if (reverse == null) { + throw new QueryException(); + } + arr.write(b, off, len); + } + + @Override + public synchronized void write(int b) throws IOException { + if (reverse == null) { + throw new QueryException(); + } + arr.write(b); + } + + @Override + public String toString() { + if (reverse == null) { + return "Reverse question was not answered yet!"; + } + if (reverse) { + StringBuilder sb = new StringBuilder(); + sb.append(arr.toString()); + sb.reverse(); + return sb.toString(); + } + return arr.toString(); + } + + private class QueryException extends UserQuestionException { + + @Override + public JOptionPane getQuestionPane() { + JOptionPane p = new JOptionPane("Store in reverse way?"); + p.setOptionType(JOptionPane.YES_NO_CANCEL_OPTION); + return p; + } + + @Override + public void confirm(Object option) { + if (option.equals(JOptionPane.YES_OPTION)) { + reverse = Boolean.TRUE; + return; + } + if (option.equals(JOptionPane.NO_OPTION)) { + reverse = Boolean.FALSE; + return; + } + } + } +} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/test/org/apidesign/exceptions/trycatchredo/IOManagerTest.java --- a/samples/exceptions/test/org/apidesign/exceptions/trycatchredo/IOManagerTest.java Sun Feb 01 16:03:37 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -package org.apidesign.exceptions.trycatchredo; - - -import java.awt.EventQueue; -import java.awt.event.ActionEvent; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URL; -import javax.swing.Action; -import javax.swing.JOptionPane; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import static org.junit.Assert.*; - -/** - * - * @author Jaroslav Tulach - */ -public class IOManagerTest { - - public IOManagerTest() { - } - - @Before - public void setUp() { - MemoryURL.initialize(); - } - - @After - public void tearDown() { - } - - @Test - public void simpleWrite() throws Exception { - URL u = new URL("memory://simpleWrite.txt"); - MemoryURL.registerURL(u.toExternalForm(), "", null); - final Action a = IOManager.createSaveAction(u, "Hello World!"); - EventQueue.invokeAndWait(new Runnable() { - public void run() { - a.actionPerformed(new ActionEvent(this, 0, "")); - } - }); - String out = MemoryURL.getOutputForURL(u.toExternalForm()); - assertEquals("Hello World!", out); - } - - @Test - public void writeWithAQuestion() throws Exception { - URL u = new URL("memory://queryEncoding.txt"); - - MemoryURL.registerURL(u.toExternalForm(), "", new QueryStream()); - final Action a = IOManager.createSaveAction(u, "Ask a Question"); - EventQueue.invokeAndWait(new Runnable() { - public void run() { - a.actionPerformed(new ActionEvent(this, 0, "")); - } - }); - String out = MemoryURL.getOutputForURL(u.toExternalForm()); - assertEquals("Text is reversed", "noitseuQ a ksA", out); - } - - private static class QueryStream extends OutputStream { - Boolean reverse; - ByteArrayOutputStream arr = new ByteArrayOutputStream(); - - @Override - public synchronized void write(byte[] b, int off, int len) throws IOException { - if (reverse == null) { - throw new QueryException(); - } - arr.write(b, off, len); - } - - @Override - public synchronized void write(int b) throws IOException { - if (reverse == null) { - throw new QueryException(); - } - arr.write(b); - } - - @Override - public String toString() { - if (reverse == null) { - return "Reverse question was not answered yet!"; - } - if (reverse) { - StringBuilder sb = new StringBuilder(); - sb.append(arr.toString()); - sb.reverse(); - return sb.toString(); - } - return arr.toString(); - } - - private class QueryException extends UserQuestionException { - @Override - public JOptionPane getQuestionPane() { - JOptionPane p = new JOptionPane("Store in reverse way?"); - p.setOptionType(JOptionPane.YES_NO_CANCEL_OPTION); - return p; - } - - @Override - public void confirm(Object option) { - if (option.equals(JOptionPane.YES_OPTION)) { - reverse = Boolean.TRUE; - return; - } - if (option.equals(JOptionPane.NO_OPTION)) { - reverse = Boolean.FALSE; - return; - } - } - } // end of QueryException - } // end of QueryStream - - -} \ No newline at end of file diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/test/org/apidesign/exceptions/trycatchredo/MemoryURL.java --- a/samples/exceptions/test/org/apidesign/exceptions/trycatchredo/MemoryURL.java Sun Feb 01 16:03:37 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ - -package org.apidesign.exceptions.trycatchredo; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; -import java.util.HashMap; -import java.util.Map; -import junit.framework.Assert; - -/** - * - * @author Jaroslav Tulach - */ -public final class MemoryURL extends URLStreamHandler { - private MemoryURL() { - } - - static void initialize() { - } - static { - class F implements URLStreamHandlerFactory { - public URLStreamHandler createURLStreamHandler(String protocol) { - if (protocol.startsWith("memory")) { - return new MemoryURL(); - } - return null; - } - } - F f = new F(); - URL.setURLStreamHandlerFactory(f); - } - - private static Map contents = new HashMap(); - private static Map outputs = new HashMap(); - public static void registerURL(String u, String content, OutputStream out) throws MalformedURLException { - contents.put(u, new ByteArrayInputStream(content.getBytes())); - outputs.put(u, out); - } - - public static String getOutputForURL(String u) { - OutputStream out = outputs.get(u); - Assert.assertNotNull("No output for " + u, out); - return out.toString(); - } - - protected URLConnection openConnection(URL u) throws IOException { - return new MC(u); - } - - private static final class MC extends URLConnection { - private InputStream values; - private OutputStream out; - - public MC(URL u) { - super(u); - out = outputs.get(u.toExternalForm()); - if (out == null) { - out = new ByteArrayOutputStream(); - outputs.put(u.toExternalForm(), out); - } - } - - public void connect() throws IOException { - if (values != null) { - return; - } - values = contents.remove(url.toExternalForm()); - if (values == null) { - throw new IOException("No such content: " + url); - } - } - - @Override - public InputStream getInputStream() throws IOException { - connect(); - return values; - } - - @Override - public OutputStream getOutputStream() throws IOException { - if (out == null) { - out = new ByteArrayOutputStream(); - } - return out; - } - } -} diff -r fba31e9504a1 -r cb8db49f9d1c samples/exceptions/test/org/apidesign/exceptions/trycatchredo/api/IOManagerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptions/test/org/apidesign/exceptions/trycatchredo/api/IOManagerTest.java Sun Feb 01 16:27:41 2009 +0100 @@ -0,0 +1,64 @@ +package org.apidesign.exceptions.trycatchredo.api; + + +import org.apidesign.exceptions.trycatchredo.usage.MemoryURL; +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.net.URL; +import javax.swing.Action; +import javax.swing.JOptionPane; +import org.apidesign.exceptions.trycatchredo.usage.QueryStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author Jaroslav Tulach + */ +public class IOManagerTest { + + public IOManagerTest() { + } + + @Before + public void setUp() { + MemoryURL.initialize(); + } + + @After + public void tearDown() { + } + + @Test + public void simpleWrite() throws Exception { + URL u = new URL("memory://simpleWrite.txt"); + MemoryURL.registerURL(u.toExternalForm(), "", null); + final Action a = IOManager.createSaveAction(u, "Hello World!"); + EventQueue.invokeAndWait(new Runnable() { + public void run() { + a.actionPerformed(new ActionEvent(this, 0, "")); + } + }); + String out = MemoryURL.getOutputForURL(u.toExternalForm()); + assertEquals("Hello World!", out); + } + + @Test + public void writeWithAQuestion() throws Exception { + URL u = new URL("memory://queryEncoding.txt"); + + MemoryURL.registerURL(u.toExternalForm(), "", new QueryStream()); + final Action a = IOManager.createSaveAction(u, "Ask a Question"); + // simulate that the user clicks Yes to the reverse question in the dialog + IOManager.setVisibleOption = JOptionPane.YES_OPTION; + EventQueue.invokeAndWait(new Runnable() { + public void run() { + a.actionPerformed(new ActionEvent(this, 0, "")); + } + }); + String out = MemoryURL.getOutputForURL(u.toExternalForm()); + assertEquals("Text is reversed", "noitseuQ a ksA", out); + } +} \ No newline at end of file