1/* 2 * Copyright (c) 1997, 2013, 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 26package com.sun.xml.internal.ws.api.pipe; 27 28import com.sun.xml.internal.ws.api.message.Packet; 29import java.util.concurrent.Executor; 30 31/** 32 * Indicates what shall happen after {@link Tube#processRequest(Packet)} or 33 * {@link Tube#processResponse(Packet)} returns. 34 * 35 * <p> 36 * To allow reuse of this object, this class is mutable. 37 * 38 * @author Kohsuke Kawaguchi 39 */ 40public final class NextAction { 41 int kind; 42 Tube next; 43 Packet packet; 44 /** 45 * Really either {@link RuntimeException} or {@link Error}. 46 */ 47 Throwable throwable; 48 Runnable onExitRunnable; 49 50 // public enum Kind { INVOKE, INVOKE_AND_FORGET, RETURN, SUSPEND } 51 52 static final int INVOKE = 0; 53 static final int INVOKE_AND_FORGET = 1; 54 static final int RETURN = 2; 55 static final int THROW = 3; 56 static final int SUSPEND = 4; 57 // Used to abort processResponse chain if a fatal exception is encountered 58 static final int THROW_ABORT_RESPONSE = 5; 59 // Used to abort processResponse chain if a response should be aborted 60 static final int ABORT_RESPONSE = 6; 61 // Used to switch a tubeline from synchronous to asynchronous execution 62 // with respect to the thread that started this tubeline. 63 static final int INVOKE_ASYNC = 7; 64 65 private void set(int k, Tube v, Packet p, Throwable t) { 66 this.kind = k; 67 this.next = v; 68 this.packet = p; 69 this.throwable = t; 70 } 71 72 /** 73 * Indicates that the next action should be to 74 * invoke the next tube's {@link Tube#processRequest(Packet)}, 75 * then later invoke the current tube's {@link Tube#processResponse(Packet)} 76 * with the response packet. 77 */ 78 public void invoke(Tube next, Packet p) { 79 set(INVOKE, next, p, null); 80 } 81 82 /** 83 * Indicates that the next action should be to 84 * invoke the next tube's {@link Tube#processRequest(Packet)}, 85 * but the current tube doesn't want to receive the response packet to 86 * its {@link Tube#processResponse(Packet)}. 87 */ 88 public void invokeAndForget(Tube next, Packet p) { 89 set(INVOKE_AND_FORGET, next, p, null); 90 } 91 92 /** 93 * Indicates that the next action is to flip the processing direction 94 * and starts response processing. 95 */ 96 public void returnWith( Packet response ) { 97 set(RETURN, null, response, null); 98 } 99 100 /** 101 * Indicates that the next action is to flip the processing direction 102 * and starts exception processing, but with the indicated context. 103 * 104 * @param t 105 * Either {@link RuntimeException} or {@link Error}, but defined to 106 * take {@link Throwable} because {@link Tube#processException(Throwable)} 107 * takes {@link Throwable}. 108 */ 109 public void throwException( Packet response, Throwable t ) { 110 // Use of RETURN is correct -- Fiber processing does not set packet for type of THROW 111 set(RETURN, null, response, t); 112 } 113 114 /** 115 * Indicates that the next action is to flip the processing direction 116 * and starts exception processing. 117 * 118 * @param t 119 * Either {@link RuntimeException} or {@link Error}, but defined to 120 * take {@link Throwable} because {@link Tube#processException(Throwable)} 121 * takes {@link Throwable}. 122 */ 123 public void throwException(Throwable t) { 124 assert t instanceof RuntimeException || t instanceof Error; 125 set(THROW,null,null,t); 126 } 127 128 /** 129 * Indicates that the next action is to abort the processResponse chain 130 * because of an exception. How that exception is processed is not 131 * defined. 132 * 133 * @param t 134 * Either {@link RuntimeException} or {@link Error} 135 */ 136 public void throwExceptionAbortResponse(Throwable t) { 137 set(THROW_ABORT_RESPONSE,null,null,t); 138 } 139 140 /** 141 * Indicates that the next action is to abort the processResponse chain 142 * because of some non-exception condition. 143 * 144 * @param response The response that is being aborted 145 */ 146 public void abortResponse(Packet response) { 147 set(ABORT_RESPONSE,null,response,null); 148 } 149 150 /** 151 * Indicates that the next action is to invoke the next tube in the 152 * tubeline async from the thread that started the tubeline. Only fibers 153 * that were started using startSync should use this next action kind. 154 * @param next The next tube in the tubeline 155 * @param p The request to pass to the next tube 156 */ 157 public void invokeAsync(Tube next, Packet p) { 158 set(INVOKE_ASYNC,next,p,null); 159 } 160 161 /** 162 * Indicates that the fiber should be suspended. 163 * Once {@link Fiber#resume(Packet) resumed}, return the response processing. 164 * @deprecated Use variants that pass {@link Runnable} 165 */ 166 public void suspend() { 167 suspend(null, null); 168 } 169 170 /** 171 * Indicates that the fiber should be suspended. Once the current {@link Thread} 172 * exits the fiber's control loop, the onExitRunnable will be invoked. This {@link Runnable} 173 * may call {@link Fiber#resume(Packet)}; however it is still guaranteed that the current 174 * Thread will return control, therefore, further processing will be handled on a {@link Thread} 175 * from the {@link Executor}. For synchronous cases, the Thread invoking this fiber cannot return 176 * until fiber processing is complete; therefore, the guarantee is only that the onExitRunnable 177 * will be invoked prior to completing the suspension. 178 * @since 2.2.7 179 */ 180 public void suspend(Runnable onExitRunnable) { 181 suspend(null, onExitRunnable); 182 } 183 184 /** 185 * Indicates that the fiber should be suspended. 186 * Once {@link Fiber#resume(Packet) resumed}, resume with the 187 * {@link Tube#processRequest(Packet)} on the given next tube. 188 * @deprecated Use variants that pass {@link Runnable} 189 */ 190 public void suspend(Tube next) { 191 suspend(next, null); 192 } 193 194 /** 195 * Indicates that the fiber should be suspended. Once the current {@link Thread} 196 * exits the fiber's control loop, the onExitRunnable will be invoked. This {@link Runnable} 197 * may call {@link Fiber#resume(Packet)}; however it is still guaranteed that the current 198 * fiber will return control, therefore, further processing will be handled on a {@link Thread} 199 * from the {@link Executor}. For synchronous cases, the Thread invoking this fiber cannot return 200 * until fiber processing is complete; therefore, the guarantee is only that the onExitRunnable 201 * will be invoked prior to completing the suspension. 202 * <p> 203 * Once {@link Fiber#resume(Packet) resumed}, resume with the 204 * {@link Tube#processRequest(Packet)} on the given next tube. 205 * @since 2.2.7 206 */ 207 public void suspend(Tube next, Runnable onExitRunnable) { 208 set(SUSPEND, next, null, null); 209 this.onExitRunnable = onExitRunnable; 210 } 211 212 /** Returns the next tube 213 * @return Next tube 214 */ 215 public Tube getNext() { 216 return next; 217 } 218 219 /** Sets the next tube 220 * @param next Next tube 221 */ 222 public void setNext(Tube next) { 223 this.next = next; 224 } 225 226 /** 227 * Returns the last Packet 228 * @return Packet 229 */ 230 public Packet getPacket() { 231 return packet; 232 } 233 234 /** 235 * Returns the Throwable generated by the last Tube 236 * @return the Throwable 237 */ 238 public Throwable getThrowable() { 239 return throwable; 240 } 241 242 /** 243 * Dumps the contents to assist debugging. 244 */ 245 @Override 246 public String toString() { 247 StringBuilder buf = new StringBuilder(); 248 buf.append(super.toString()).append(" ["); 249 buf.append("kind=").append(getKindString()).append(','); 250 buf.append("next=").append(next).append(','); 251 buf.append("packet=").append(packet != null ? packet.toShortString() : null).append(','); 252 buf.append("throwable=").append(throwable).append(']'); 253 return buf.toString(); 254 } 255 256 /** 257 * Returns {@link #kind} in a human readable string, to assist debugging. 258 */ 259 public String getKindString() { 260 switch(kind) { 261 case INVOKE: return "INVOKE"; 262 case INVOKE_AND_FORGET: return "INVOKE_AND_FORGET"; 263 case RETURN: return "RETURN"; 264 case THROW: return "THROW"; 265 case SUSPEND: return "SUSPEND"; 266 case THROW_ABORT_RESPONSE: return "THROW_ABORT_RESPONSE"; 267 case ABORT_RESPONSE: return "ABORT_RESPONSE"; 268 case INVOKE_ASYNC: return "INVOKE_ASYNC"; 269 default: throw new AssertionError(kind); 270 } 271 } 272} 273