Checking in Ray's update to ServiceWaiter.

git-svn-id: https://samskivert.googlecode.com/svn/trunk@2374 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
andrzej@threerings.net
2008-08-28 23:08:04 +00:00
parent 403200041e
commit add5867c13
+200 -202
View File
@@ -1,202 +1,200 @@
// //
// $Id$ // $Id$
// //
// samskivert library - useful routines for java programs // samskivert library - useful routines for java programs
// Copyright (C) 2001-2007 Michael Bayne // Copyright (C) 2001-2007 Michael Bayne
// //
// This library is free software; you can redistribute it and/or modify it // This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published // under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or // by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This library is distributed in the hope that it will be useful, // This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details. // Lesser General Public License for more details.
// //
// You should have received a copy of the GNU Lesser General Public // You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software // License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.util; package com.samskivert.util;
/** /**
* A handy base class for issuing server-side service requests and * A handy base class for issuing server-side service requests and
* awaiting their responses from within a servlet. * awaiting their responses from within a servlet.
* *
* <em>Note:</em> You might think that it would be keen to use this * <em>Note:</em> You might think that it would be keen to use this
* anonymously like so: * anonymously like so:
* *
* <pre> * <pre>
* ServiceWaiter waiter = new ServiceWaiter() { * ServiceWaiter waiter = new ServiceWaiter() {
* public void handleSuccess (int invid, ...) { * public void handleSuccess (int invid, ...) {
* // handle success * // handle success
* } * }
* // ... * // ...
* }; * };
* </pre> * </pre>
* *
* But that won't work because public methods in anonymous inner classes * 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 * 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 * able to reflect your response methods when the time comes to deliver
* the response. Unfortunately, there appears to be no manner in which to * the response. Unfortunately, there appears to be no manner in which to
* instruct the Java compiler to give public scope to an anonymous inner * instruct the Java compiler to give public scope to an anonymous inner
* class rather than default scope. Sigh. * class rather than default scope. Sigh.
*/ */
public class ServiceWaiter<T> public class ServiceWaiter<T>
implements ResultListener<T> implements ResultListener<T>
{ {
/** Timeout to specify when you don't want a timeout. Use at your own /** Timeout to specify when you don't want a timeout. Use at your own
* risk. */ * risk. */
public static final int NO_TIMEOUT = -1; public static final int NO_TIMEOUT = -1;
public static class TimeoutException extends Exception public static class TimeoutException extends Exception
{ {
public TimeoutException () public TimeoutException ()
{ {
super("Timeout! Pow!"); super("Timeout! Pow!");
} }
} }
/** /**
* Construct a ServiceWaiter with the default (30 second) timeout. * Construct a ServiceWaiter with the default (30 second) timeout.
*/ */
public ServiceWaiter () public ServiceWaiter ()
{ {
this(DEFAULT_WAITER_TIMEOUT); this(DEFAULT_WAITER_TIMEOUT);
} }
/** /**
* Construct a ServiceWaiter with the specified timeout. * Construct a ServiceWaiter with the specified timeout.
* *
* @param timeout the timeout, in seconds. * @param timeout the timeout, in seconds.
*/ */
public ServiceWaiter (int timeout) public ServiceWaiter (int timeout)
{ {
setTimeout(timeout); setTimeout(timeout);
} }
/** /**
* Change the timeout being used for this ServiceWaiter after it * Change the timeout being used for this ServiceWaiter after it
* has been constructed. * has been constructed.
*/ */
public void setTimeout (int timeout) public void setTimeout (int timeout)
{ {
_timeout = timeout; _timeout = timeout;
} }
/** /**
* Reset the service waiter so that it can be used again. * Reset the service waiter so that it can be used again.
*/ */
public synchronized void reset () public synchronized void reset ()
{ {
_success = 0; _success = 0;
_argument = null; _argument = null;
} }
/** /**
* Marks the request as successful and posts the supplied response * Marks the request as successful and posts the supplied response
* argument for perusal by the caller. * argument for perusal by the caller.
*/ */
public synchronized void postSuccess (T arg) public synchronized void postSuccess (T arg)
{ {
_success = 1; _success = 1;
_argument = arg; _argument = arg;
notify(); notify();
} }
/** /**
* Marks the request as failed. * Marks the request as failed.
*/ */
public synchronized void postFailure (Exception error) public synchronized void postFailure (Exception error)
{ {
_success = -1; _success = -1;
_error = error; _error = error;
notify(); notify();
} }
/** /**
* Returns the argument posted by the waiter when the response * Returns the argument posted by the waiter when the response
* arrived. * arrived.
*/ */
public T getArgument () public T getArgument ()
{ {
return _argument; return _argument;
} }
/** /**
* Returns the exception posted in the event of failure. * Returns the exception posted in the event of failure.
*/ */
public Exception getError () public Exception getError ()
{ {
return _error; return _error;
} }
/** /**
* Blocks waiting for the response. * Blocks waiting for the response.
* *
* @return true if a success response was posted, false if a failure * @return true if a success response was posted, false if a failure
* repsonse was posted. * repsonse was posted.
*/ */
public boolean waitForResponse () public boolean waitForResponse ()
throws TimeoutException throws TimeoutException
{ {
if (_success == 0) { if (_success == 0) {
synchronized (this) { synchronized (this) {
while (_success == 0) { try {
try { // wait for the response, timing out after a while
// wait for the response, timing out after a while if (_timeout == NO_TIMEOUT) {
if (_timeout == NO_TIMEOUT) { wait();
wait();
} else {
} else { wait(1000L * _timeout);
wait(1000L * _timeout); }
} // if we get here without some sort of response, then
// we've timed out
// if we get here without some sort of response, then if (_success == 0) {
// we've timed out throw new TimeoutException();
if (_success == 0) { }
throw new TimeoutException();
} } catch (InterruptedException ie) {
throw (TimeoutException)
} catch (InterruptedException ie) { new TimeoutException().initCause(ie);
// fall through and wait again }
} }
} }
}
} return (_success > 0);
}
return (_success > 0);
} // documentation inherited from interface ResultListener
public void requestCompleted (T result)
// documentation inherited from interface ResultListener {
public void requestCompleted (T result) postSuccess(result);
{ }
postSuccess(result);
} // documentation inherited from interface ResultListener
public void requestFailed (Exception cause)
// documentation inherited from interface ResultListener {
public void requestFailed (Exception cause) postFailure(cause);
{ }
postFailure(cause);
} /** Whether or not the response succeeded; positive for success,
* negative for failure, zero means we haven't received the response
/** Whether or not the response succeeded; positive for success, * yet. */
* negative for failure, zero means we haven't received the response protected int _success = 0;
* yet. */
protected int _success = 0; /** The argument posted by the waiter upon receipt of the response. */
protected T _argument;
/** The argument posted by the waiter upon receipt of the response. */
protected T _argument; /** The exception posted by the waiter upon failure. */
protected Exception _error;
/** The exception posted by the waiter upon failure. */
protected Exception _error; /** How many seconds to wait before giving up the ghost. */
protected int _timeout;
/** 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
/** If a response is not received within the specified timeout, an * page. */
* exception is thrown which redirects the user to an internal error protected static final int DEFAULT_WAITER_TIMEOUT = 30;
* page. */ }
protected static final int DEFAULT_WAITER_TIMEOUT = 30;
}