package er.extensions.concurrency; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOApplication; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOResponse; import er.extensions.components.ERXNonSynchronizingComponent; import er.extensions.eof.ERXConstant; /** * ERXLongResponse is like WOLongResponsePage from JavaWOExtensions, but * it can be used as a component and doesn't need to be subclassed. * Instead, you provide a ERXLongResponseTask subclass and set it * via either the bindings or explicitely. * * @binding task implementation of ERXLongResponseTask * * @author ak on Tue Feb 03 2004 */ public class ERXLongResponse extends ERXNonSynchronizingComponent { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; static String WOMetaRefreshSenderId = "WOMetaRefresh"; protected Number _refreshInterval; protected boolean _performingAction; protected boolean _doneAndRefreshed; protected ERXLongResponseTask _task; public ERXLongResponse(WOContext aContext) { super(aContext); _doneAndRefreshed = false; _refreshInterval = ERXConstant.ZeroInteger; _performingAction = false; } public ERXLongResponseTask task() { if(_task == null) { _task = (ERXLongResponseTask)valueForBinding("task"); } return _task; } public void setTask(ERXLongResponseTask task) { _task = task; } public int refreshInterval() { if(ERXConstant.ZeroInteger.equals(_refreshInterval)) { Number n = (Number)valueForBinding("refreshInterval"); if(n != null) { _refreshInterval = n; } } return _refreshInterval.intValue(); } public void setRefreshInterval(int value) { _refreshInterval = Integer.valueOf(value); } public WOComponent refresh() { return task().nextPage(); } @Override public void appendToResponse(WOResponse aResponse, WOContext aContext) { if (!_performingAction) { _performingAction = true; task().setLongResponse(this); task().start(); } boolean done = task().isDone(); boolean doneButNotRefreshed = done && !_doneAndRefreshed; // If the refreshInterval was set and we did not get a result yet, let's add the refresh header. int interval = (doneButNotRefreshed ? 0 : refreshInterval()); if(!done || (doneButNotRefreshed)) { // If the response is done and finished quickly (before the first branch of this conditional is invoked), // make sure to refresh the page immediately. String modifiedDynamicUrl = aContext.urlWithRequestHandlerKey(WOApplication.application().componentRequestHandlerKey(), null, null); String query = ""; if (modifiedDynamicUrl.contains("?")) { query = modifiedDynamicUrl.substring(modifiedDynamicUrl.indexOf("?")); modifiedDynamicUrl = modifiedDynamicUrl.substring(0, modifiedDynamicUrl.indexOf("?")); } String header = interval + ";url=" +modifiedDynamicUrl+ "/" + aContext.session().sessionID()+ "/" +aContext.contextID()+ "." +WOMetaRefreshSenderId + query; aResponse.setHeader(header, "Refresh"); if((doneButNotRefreshed)) { _doneAndRefreshed = true; } } super.appendToResponse(aResponse, aContext); } @Override public WOActionResults invokeAction(WORequest aRequest, WOContext aContext) { if (aContext.senderID().equals(WOMetaRefreshSenderId)) { // We recognized the elementID that was set for the meta refresh. // we know which action to call, it is -returnRefreshedPage. return refresh(); } return super.invokeAction(aRequest, aContext); } }