blob: d7f17b36c335667ecaf9b3da2fe51b66285723af [file] [log] [blame]
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.ws.api.pipe;
import com.sun.xml.internal.ws.api.message.Packet;
import java.util.concurrent.Executor;
/**
* Indicates what shall happen after {@link Tube#processRequest(Packet)} or
* {@link Tube#processResponse(Packet)} returns.
*
* <p>
* To allow reuse of this object, this class is mutable.
*
* @author Kohsuke Kawaguchi
*/
public final class NextAction {
int kind;
Tube next;
Packet packet;
/**
* Really either {@link RuntimeException} or {@link Error}.
*/
Throwable throwable;
Runnable onExitRunnable;
// public enum Kind { INVOKE, INVOKE_AND_FORGET, RETURN, SUSPEND }
static final int INVOKE = 0;
static final int INVOKE_AND_FORGET = 1;
static final int RETURN = 2;
static final int THROW = 3;
static final int SUSPEND = 4;
// Used to abort processResponse chain if a fatal exception is encountered
static final int THROW_ABORT_RESPONSE = 5;
// Used to abort processResponse chain if a response should be aborted
static final int ABORT_RESPONSE = 6;
// Used to switch a tubeline from synchronous to asynchronous execution
// with respect to the thread that started this tubeline.
static final int INVOKE_ASYNC = 7;
private void set(int k, Tube v, Packet p, Throwable t) {
this.kind = k;
this.next = v;
this.packet = p;
this.throwable = t;
}
/**
* Indicates that the next action should be to
* invoke the next tube's {@link Tube#processRequest(Packet)},
* then later invoke the current tube's {@link Tube#processResponse(Packet)}
* with the response packet.
*/
public void invoke(Tube next, Packet p) {
set(INVOKE, next, p, null);
}
/**
* Indicates that the next action should be to
* invoke the next tube's {@link Tube#processRequest(Packet)},
* but the current tube doesn't want to receive the response packet to
* its {@link Tube#processResponse(Packet)}.
*/
public void invokeAndForget(Tube next, Packet p) {
set(INVOKE_AND_FORGET, next, p, null);
}
/**
* Indicates that the next action is to flip the processing direction
* and starts response processing.
*/
public void returnWith( Packet response ) {
set(RETURN, null, response, null);
}
/**
* Indicates that the next action is to flip the processing direction
* and starts exception processing, but with the indicated context.
*
* @param t
* Either {@link RuntimeException} or {@link Error}, but defined to
* take {@link Throwable} because {@link Tube#processException(Throwable)}
* takes {@link Throwable}.
*/
public void throwException( Packet response, Throwable t ) {
// Use of RETURN is correct -- Fiber processing does not set packet for type of THROW
set(RETURN, null, response, t);
}
/**
* Indicates that the next action is to flip the processing direction
* and starts exception processing.
*
* @param t
* Either {@link RuntimeException} or {@link Error}, but defined to
* take {@link Throwable} because {@link Tube#processException(Throwable)}
* takes {@link Throwable}.
*/
public void throwException(Throwable t) {
assert t instanceof RuntimeException || t instanceof Error;
set(THROW,null,null,t);
}
/**
* Indicates that the next action is to abort the processResponse chain
* because of an exception. How that exception is processed is not
* defined.
*
* @param t
* Either {@link RuntimeException} or {@link Error}
*/
public void throwExceptionAbortResponse(Throwable t) {
set(THROW_ABORT_RESPONSE,null,null,t);
}
/**
* Indicates that the next action is to abort the processResponse chain
* because of some non-exception condition.
*
* @param response The response that is being aborted
*/
public void abortResponse(Packet response) {
set(ABORT_RESPONSE,null,response,null);
}
/**
* Indicates that the next action is to invoke the next tube in the
* tubeline async from the thread that started the tubeline. Only fibers
* that were started using startSync should use this next action kind.
* @param next The next tube in the tubeline
* @param p The request to pass to the next tube
*/
public void invokeAsync(Tube next, Packet p) {
set(INVOKE_ASYNC,next,p,null);
}
/**
* Indicates that the fiber should be suspended.
* Once {@link Fiber#resume(Packet) resumed}, return the response processing.
* @deprecated Use variants that pass {@link Runnable}
*/
public void suspend() {
suspend(null, null);
}
/**
* Indicates that the fiber should be suspended. Once the current {@link Thread}
* exits the fiber's control loop, the onExitRunnable will be invoked. This {@link Runnable}
* may call {@link Fiber#resume(Packet)}; however it is still guaranteed that the current
* Thread will return control, therefore, further processing will be handled on a {@link Thread}
* from the {@link Executor}. For synchronous cases, the Thread invoking this fiber cannot return
* until fiber processing is complete; therefore, the guarantee is only that the onExitRunnable
* will be invoked prior to completing the suspension.
* @since 2.2.7
*/
public void suspend(Runnable onExitRunnable) {
suspend(null, onExitRunnable);
}
/**
* Indicates that the fiber should be suspended.
* Once {@link Fiber#resume(Packet) resumed}, resume with the
* {@link Tube#processRequest(Packet)} on the given next tube.
* @deprecated Use variants that pass {@link Runnable}
*/
public void suspend(Tube next) {
suspend(next, null);
}
/**
* Indicates that the fiber should be suspended. Once the current {@link Thread}
* exits the fiber's control loop, the onExitRunnable will be invoked. This {@link Runnable}
* may call {@link Fiber#resume(Packet)}; however it is still guaranteed that the current
* fiber will return control, therefore, further processing will be handled on a {@link Thread}
* from the {@link Executor}. For synchronous cases, the Thread invoking this fiber cannot return
* until fiber processing is complete; therefore, the guarantee is only that the onExitRunnable
* will be invoked prior to completing the suspension.
* <p>
* Once {@link Fiber#resume(Packet) resumed}, resume with the
* {@link Tube#processRequest(Packet)} on the given next tube.
* @since 2.2.7
*/
public void suspend(Tube next, Runnable onExitRunnable) {
set(SUSPEND, next, null, null);
this.onExitRunnable = onExitRunnable;
}
/** Returns the next tube
* @return Next tube
*/
public Tube getNext() {
return next;
}
/** Sets the next tube
* @param next Next tube
*/
public void setNext(Tube next) {
this.next = next;
}
/**
* Returns the last Packet
* @return Packet
*/
public Packet getPacket() {
return packet;
}
/**
* Returns the Throwable generated by the last Tube
* @return the Throwable
*/
public Throwable getThrowable() {
return throwable;
}
/**
* Dumps the contents to assist debugging.
*/
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(super.toString()).append(" [");
buf.append("kind=").append(getKindString()).append(',');
buf.append("next=").append(next).append(',');
buf.append("packet=").append(packet != null ? packet.toShortString() : null).append(',');
buf.append("throwable=").append(throwable).append(']');
return buf.toString();
}
/**
* Returns {@link #kind} in a human readable string, to assist debugging.
*/
public String getKindString() {
switch(kind) {
case INVOKE: return "INVOKE";
case INVOKE_AND_FORGET: return "INVOKE_AND_FORGET";
case RETURN: return "RETURN";
case THROW: return "THROW";
case SUSPEND: return "SUSPEND";
case THROW_ABORT_RESPONSE: return "THROW_ABORT_RESPONSE";
case ABORT_RESPONSE: return "ABORT_RESPONSE";
case INVOKE_ASYNC: return "INVOKE_ASYNC";
default: throw new AssertionError(kind);
}
}
}