diff --git a/projects/samskivert/src/java/com/samskivert/servlet/util/ServiceWaiter.java b/projects/samskivert/src/java/com/samskivert/servlet/util/ServiceWaiter.java index 933dfe3a..fb564e2f 100644 --- a/projects/samskivert/src/java/com/samskivert/servlet/util/ServiceWaiter.java +++ b/projects/samskivert/src/java/com/samskivert/servlet/util/ServiceWaiter.java @@ -1,37 +1,14 @@ // -// $Id: ServiceWaiter.java,v 1.2 2003/08/13 01:55:05 ray Exp $ +// $Id: ServiceWaiter.java,v 1.3 2003/08/15 02:23:47 ray Exp $ package com.samskivert.servlet.util; -import com.samskivert.Log; import com.samskivert.servlet.RedirectException; -import com.samskivert.util.ResultListener; /** - * A handy base class for issuing server-side service requests and - * awaiting their responses from within a servlet. - * - * Note: You might think that it would be keen to use this - * anonymously like so: - * - *
- * ServiceWaiter waiter = new ServiceWaiter() {
- *     public void handleSuccess (int invid, ...) {
- *         // handle success
- *     }
- *     // ...
- * };
- * 
- * - * But that won't work because public methods in anonymous inner classes - * do not have public visibility and so the invocation manager will not be - * able to reflect your response methods when the time comes to deliver - * the response. Unfortunately, there appears to be no manner in which to - * instruct the Java compiler to give public scope to an anonymous inner - * class rather than default scope. Sigh. + * Extends the basic ServiceWaiter to be useful for servlets. */ -public class ServiceWaiter - implements ResultListener +public class ServiceWaiter extends com.samskivert.util.ServiceWaiter { /** Timeout to specify when you don't want a timeout. Use at your own * risk. */ @@ -42,7 +19,7 @@ public class ServiceWaiter */ public ServiceWaiter () { - this(DEFAULT_WAITER_TIMEOUT); + super(); } /** @@ -52,56 +29,7 @@ public class ServiceWaiter */ public ServiceWaiter (int timeout) { - setTimeout(timeout); - } - - /** - * Change the timeout being used for this ServiceWaiter after it - * has been constructed. - */ - public void setTimeout (int timeout) - { - _timeout = timeout; - } - - /** - * Reset the service waiter so that it can be used again. - */ - public void reset () - { - _success = 0; - _argument = null; - } - - /** - * Marks the request as successful and posts the supplied response - * argument for perusal by the caller. - */ - public synchronized void postSuccess (Object arg) - { - _success = 1; - _argument = arg; - notify(); - } - - /** - * Marks the request as failed and posts the supplied response - * argument for perusal by the caller. - */ - public synchronized void postFailure (Object arg) - { - _success = -1; - _argument = arg; - notify(); - } - - /** - * Returns the argument posted by the waiter when the response - * arrived. - */ - public Object getArgument () - { - return _argument; + super(timeout); } /** @@ -110,33 +38,15 @@ public class ServiceWaiter * @return true if a success response was posted, false if a failure * repsonse was posted. */ - public synchronized boolean awaitResponse () + public boolean awaitResponse () throws RedirectException { - while (_success == 0) { - try { - // wait for the response, timing out after a while - if (_timeout == NO_TIMEOUT) { - wait(); + try { + return waitForResponse(); - } else { - wait(1000L * _timeout); - } - - // if we get here without some sort of response, then - // we've timed out and we should freak out - if (_success == 0) { - Log.warning("Service waiter timed out."); - Thread.dumpStack(); - throw new RedirectException(getTimeoutRedirectURL()); - } - - } catch (InterruptedException ie) { - // fall through and wait again - } + } catch (TimeoutException te) { + throw new RedirectException(getTimeoutRedirectURL()); } - - return (_success > 0); } /** @@ -147,32 +57,4 @@ public class ServiceWaiter // TODO return "/"; } - - // documentation inherited from interface ResultListener - public void requestCompleted (Object result) - { - postSuccess(result); - } - - // documentation inherited from interface ResultListener - public void requestFailed (Exception cause) - { - postFailure((cause != null) ? cause.getMessage() : null); - } - - /** Whether or not the response succeeded; positive for success, - * negative for failure, zero means we haven't received the response - * yet. */ - protected int _success = 0; - - /** The argument posted by the waiter upon receipt of the response. */ - protected Object _argument; - - /** How many seconds to wait before giving up the ghost. */ - protected int _timeout; - - /** If a response is not received within the specified timeout, an - * exception is thrown which redirects the user to an internal error - * page. */ - protected static final int DEFAULT_WAITER_TIMEOUT = 30; } diff --git a/projects/samskivert/src/java/com/samskivert/util/ServiceWaiter.java b/projects/samskivert/src/java/com/samskivert/util/ServiceWaiter.java new file mode 100644 index 00000000..8d6c5729 --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/util/ServiceWaiter.java @@ -0,0 +1,175 @@ +// +// $Id: ServiceWaiter.java,v 1.1 2003/08/15 02:23:47 ray Exp $ + +package com.samskivert.util; + +import com.samskivert.Log; + +/** + * A handy base class for issuing server-side service requests and + * awaiting their responses from within a servlet. + * + * Note: You might think that it would be keen to use this + * anonymously like so: + * + *
+ * ServiceWaiter waiter = new ServiceWaiter() {
+ *     public void handleSuccess (int invid, ...) {
+ *         // handle success
+ *     }
+ *     // ...
+ * };
+ * 
+ * + * But that won't work because public methods in anonymous inner classes + * do not have public visibility and so the invocation manager will not be + * able to reflect your response methods when the time comes to deliver + * the response. Unfortunately, there appears to be no manner in which to + * instruct the Java compiler to give public scope to an anonymous inner + * class rather than default scope. Sigh. + */ +public class ServiceWaiter + implements ResultListener +{ + /** Timeout to specify when you don't want a timeout. Use at your own + * risk. */ + public static final int NO_TIMEOUT = -1; + + public static class TimeoutException extends Exception + { + public TimeoutException () + { + super("Timeout! Pow!"); + } + } + + /** + * Construct a ServiceWaiter with the default (30 second) timeout. + */ + public ServiceWaiter () + { + this(DEFAULT_WAITER_TIMEOUT); + } + + /** + * Construct a ServiceWaiter with the specified timeout. + * + * @param timeout the timeout, in seconds. + */ + public ServiceWaiter (int timeout) + { + setTimeout(timeout); + } + + /** + * Change the timeout being used for this ServiceWaiter after it + * has been constructed. + */ + public void setTimeout (int timeout) + { + _timeout = timeout; + } + + /** + * Reset the service waiter so that it can be used again. + */ + public void reset () + { + _success = 0; + _argument = null; + } + + /** + * Marks the request as successful and posts the supplied response + * argument for perusal by the caller. + */ + public synchronized void postSuccess (Object arg) + { + _success = 1; + _argument = arg; + notify(); + } + + /** + * Marks the request as failed and posts the supplied response + * argument for perusal by the caller. + */ + public synchronized void postFailure (Object arg) + { + _success = -1; + _argument = arg; + notify(); + } + + /** + * Returns the argument posted by the waiter when the response + * arrived. + */ + public Object getArgument () + { + return _argument; + } + + /** + * Blocks waiting for the response. + * + * @return true if a success response was posted, false if a failure + * repsonse was posted. + */ + public synchronized boolean waitForResponse () + throws TimeoutException + { + while (_success == 0) { + try { + // wait for the response, timing out after a while + if (_timeout == NO_TIMEOUT) { + wait(); + + } else { + wait(1000L * _timeout); + } + + // if we get here without some sort of response, then + // we've timed out and we should freak out + if (_success == 0) { + Log.warning("Service waiter timed out."); + Thread.dumpStack(); + throw new TimeoutException(); + } + + } catch (InterruptedException ie) { + // fall through and wait again + } + } + + return (_success > 0); + } + + // documentation inherited from interface ResultListener + public void requestCompleted (Object result) + { + postSuccess(result); + } + + // documentation inherited from interface ResultListener + public void requestFailed (Exception cause) + { + postFailure((cause != null) ? cause.getMessage() : null); + } + + /** Whether or not the response succeeded; positive for success, + * negative for failure, zero means we haven't received the response + * yet. */ + protected int _success = 0; + + /** The argument posted by the waiter upon receipt of the response. */ + protected Object _argument; + + /** How many seconds to wait before giving up the ghost. */ + protected int _timeout; + + /** If a response is not received within the specified timeout, an + * exception is thrown which redirects the user to an internal error + * page. */ + protected static final int DEFAULT_WAITER_TIMEOUT = 30; +}