1 /*
   2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.ws.api.pipe;
  27 
  28 import com.sun.xml.internal.ws.api.message.Packet;
  29 
  30 /**
  31  * Indicates what shall happen after {@link Tube#processRequest(Packet)} or
  32  * {@link Tube#processResponse(Packet)} returns.
  33  *
  34  * <p>
  35  * To allow reuse of this object, this class is mutable.
  36  *
  37  * @author Kohsuke Kawaguchi
  38  */
  39 public final class NextAction {
  40     int kind;
  41     Tube next;
  42     Packet packet;
  43     /**
  44      * Really either {@link RuntimeException} or {@link Error}.
  45      */
  46     Throwable throwable;
  47 
  48     // public enum Kind { INVOKE, INVOKE_AND_FORGET, RETURN, SUSPEND }
  49 
  50     static final int INVOKE = 0;
  51     static final int INVOKE_AND_FORGET = 1;
  52     static final int RETURN = 2;
  53     static final int THROW = 3;
  54     static final int SUSPEND = 4;
  55     // Used to abort processResponse chain if a fatal exception is encountered
  56     static final int THROW_ABORT_RESPONSE = 5;
  57     // Used to abort processResponse chain if a response should be aborted
  58     static final int ABORT_RESPONSE = 6;
  59     // Used to switch a tubeline from synchronous to asynchronous execution
  60     // with respect to the thread that started this tubeline.
  61     static final int INVOKE_ASYNC = 7;
  62 
  63   private void set(int k, Tube v, Packet p, Throwable t) {
  64         this.kind = k;
  65         this.next = v;
  66         this.packet = p;
  67         this.throwable = t;
  68     }
  69 
  70     /**
  71      * Indicates that the next action should be to
  72      * invoke the next tube's {@link Tube#processRequest(Packet)},
  73      * then later invoke the current tube's {@link Tube#processResponse(Packet)}
  74      * with the response packet.
  75      */
  76     public void invoke(Tube next, Packet p) {
  77         set(INVOKE, next, p, null);
  78     }
  79 
  80     /**
  81      * Indicates that the next action should be to
  82      * invoke the next tube's {@link Tube#processRequest(Packet)},
  83      * but the current tube doesn't want to receive the response packet to
  84      * its {@link Tube#processResponse(Packet)}.
  85      */
  86     public void invokeAndForget(Tube next, Packet p) {
  87         set(INVOKE_AND_FORGET, next, p, null);
  88     }
  89 
  90     /**
  91      * Indicates that the next action is to flip the processing direction
  92      * and starts response processing.
  93      */
  94     public void returnWith( Packet response ) {
  95         set(RETURN, null, response, null);
  96     }
  97 
  98     /**
  99      * Indicates that the next action is to flip the processing direction
 100      * and starts exception processing.
 101      *
 102      * @param t
 103      *      Either {@link RuntimeException} or {@link Error}, but defined to
 104      *      take {@link Throwable} because {@link Tube#processException(Throwable)}
 105      *      takes {@link Throwable}.
 106      */
 107     public void throwException(Throwable t) {
 108         assert t instanceof RuntimeException || t instanceof Error;
 109         set(THROW,null,null,t);
 110     }
 111 
 112     /**
 113      * Indicates that the next action is to abort the processResponse chain
 114      * because of an exception. How that exception is processed is not
 115      * defined.
 116      *
 117      * @param t
 118      *      Either {@link RuntimeException} or {@link Error}
 119      */
 120     public void throwExceptionAbortResponse(Throwable t) {
 121         set(THROW_ABORT_RESPONSE,null,null,t);
 122     }
 123 
 124     /**
 125      * Indicates that the next action is to abort the processResponse chain
 126      * because of some non-exception condition.
 127      *
 128      * @param response The response that is being aborted
 129      */
 130     public void abortResponse(Packet response) {
 131         set(ABORT_RESPONSE,null,response,null);
 132     }
 133 
 134     /**
 135      * Indicates that the next action is to invoke the next tube in the
 136      * tubeline async from the thread that started the tubeline. Only fibers
 137      * that were started using startSync should use this next action kind.
 138      * @param next The next tube in the tubeline
 139      * @param p The request to pass to the next tube
 140      */
 141     public void invokeAsync(Tube next, Packet p) {
 142         set(INVOKE_ASYNC,next,p,null);
 143     }
 144 
 145     /**
 146      * Indicates that the fiber should be suspended.
 147      * Once {@link Fiber#resume(Packet) resumed}, return the response processing.
 148      */
 149     public void suspend() {
 150         set(SUSPEND, null, null, null);
 151     }
 152 
 153     /**
 154      * Indicates that the fiber should be suspended.
 155      * Once {@link Fiber#resume(Packet) resumed}, resume with the
 156      * {@link Tube#processRequest(Packet)} on the given next tube.
 157      */
 158     public void suspend(Tube next) {
 159         set(SUSPEND, next, null, null);
 160     }
 161 
 162     /** Returns the next tube
 163      * @return Next tube
 164      */
 165     public Tube getNext() {
 166         return next;
 167     }
 168 
 169     /** Sets the next tube
 170      * @param next Next tube
 171      */
 172     public void setNext(Tube next) {
 173         this.next = next;
 174     }
 175 
 176     /**
 177      * Returns the last Packet
 178      * @return Packet
 179      */
 180     public Packet getPacket() {
 181         return packet;
 182     }
 183 
 184     /**
 185      * Returns the Throwable generated by the last Tube
 186      * @return the Throwable
 187      */
 188     public Throwable getThrowable() {
 189         return throwable;
 190     }
 191 
 192     /**
 193      * Dumps the contents to assist debugging.
 194      */
 195     @Override
 196     public String toString() {
 197         StringBuilder buf = new StringBuilder();
 198         buf.append(super.toString()).append(" [");
 199         buf.append("kind=").append(getKindString()).append(',');
 200         buf.append("next=").append(next).append(',');
 201         buf.append("packet=").append(packet != null ? packet.toShortString() : null).append(',');
 202         buf.append("throwable=").append(throwable).append(']');
 203         return buf.toString();
 204     }
 205 
 206     /**
 207      * Returns {@link #kind} in a human readable string, to assist debugging.
 208      */
 209     public String getKindString() {
 210         switch(kind) {
 211         case INVOKE:            return "INVOKE";
 212         case INVOKE_AND_FORGET: return "INVOKE_AND_FORGET";
 213         case RETURN:            return "RETURN";
 214         case THROW:             return "THROW";
 215         case SUSPEND:           return "SUSPEND";
 216         case THROW_ABORT_RESPONSE: return "THROW_ABORT_RESPONSE";
 217         case ABORT_RESPONSE:    return "ABORT_RESPONSE";
 218         case INVOKE_ASYNC:      return "INVOKE_ASYNC";
 219         default:                throw new AssertionError(kind);
 220         }
 221     }
 222 }