001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.engine;
021:
022: import org.apache.axis2.AxisFault;
023: import org.apache.axis2.context.MessageContext;
024: import org.apache.axis2.description.HandlerDescription;
025: import org.apache.axis2.description.Parameter;
026: import org.apache.axis2.description.PhaseRule;
027: import org.apache.axis2.phaseresolver.PhaseException;
028: import org.apache.axis2.util.LoggingControl;
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031:
032: import java.util.ArrayList;
033: import java.util.Iterator;
034:
035: /**
036: * A Phase is an ordered collection of Handlers.
037: */
038: public class Phase implements Handler {
039:
040: public static final String ALL_PHASES = "*";
041:
042: /**
043: * Field log
044: */
045: private static final Log log = LogFactory.getLog(Phase.class);
046:
047: /**
048: * Field handlers
049: */
050: private ArrayList handlers;
051:
052: /**
053: * A handler has been marked as present in both the first phase and the last phase
054: */
055: private boolean isOneHandler;
056:
057: /**
058: * Field phaseName
059: */
060: private String phaseName;
061:
062: /**
063: * Field phaseFirstSet
064: */
065: private boolean phaseFirstSet;
066:
067: /**
068: * Field phaseLastSet
069: */
070: private boolean phaseLastSet;
071:
072: /**
073: * Default constructor
074: */
075: public Phase() {
076: this (null);
077: }
078:
079: /**
080: * Create a named Phase
081: *
082: * @param phaseName the name for this Phase
083: */
084: public Phase(String phaseName) {
085: handlers = new ArrayList();
086: this .phaseName = phaseName;
087: }
088:
089: /**
090: * Add a handler to the Phase.
091: *
092: * @param handler the Handler to add
093: */
094: public void addHandler(Handler handler) {
095: log.debug("Handler " + handler.getName() + " added to Phase "
096: + phaseName);
097:
098: if (phaseLastSet) {
099: // handlers.size() can not be 0 , since when setting phase last it is always > 0
100: if (handlers.size() == 1) {
101: handlers.add(0, handler);
102: } else {
103: handlers.add(handlers.size() - 2, handler);
104: }
105: } else {
106: handlers.add(handler);
107: }
108: }
109:
110: /**
111: * Add a HandlerDescription to the Phase
112: *
113: * @param handlerDesc the HandlerDescription to add
114: * @throws PhaseException if there is a problem
115: */
116: public synchronized void addHandler(HandlerDescription handlerDesc)
117: throws PhaseException {
118: Iterator handlers_itr = getHandlers().iterator();
119:
120: while (handlers_itr.hasNext()) {
121: Handler hand = (Handler) handlers_itr.next();
122: HandlerDescription this Desc = hand.getHandlerDesc();
123: if (handlerDesc.getName().equals(this Desc.getName())) {
124: return;
125: }
126: }
127:
128: if (isOneHandler) {
129: throw new PhaseException(
130: "Phase '"
131: + this .getPhaseName()
132: + "' can only have one handler, since there is a "
133: + "handler with both phaseFirst and phaseLast true ");
134: }
135:
136: if (handlerDesc.getRules().isPhaseFirst()
137: && handlerDesc.getRules().isPhaseLast()) {
138: if (handlers.size() > 0) {
139: throw new PhaseException(
140: this .getPhaseName()
141: + " already contains Handlers, and "
142: + handlerDesc.getName()
143: + " cannot therefore be both phaseFirst and phaseLast.");
144: } else {
145: handlers.add(handlerDesc.getHandler());
146: isOneHandler = true;
147: }
148: } else if (handlerDesc.getRules().isPhaseFirst()) {
149: setPhaseFirst(handlerDesc.getHandler());
150: } else if (handlerDesc.getRules().isPhaseLast()) {
151: setPhaseLast(handlerDesc.getHandler());
152: } else {
153: insertHandler(handlerDesc);
154: }
155: }
156:
157: /**
158: * Add a Handler at a particular index within the Phase.
159: *
160: * If we have a Phase with (H1, H2), calling addHandler(H3, 1) will result in (H1, H3, H2)
161: *
162: * @param handler the Handler to add
163: * @param index the position in the Phase at which to place the Handler
164: */
165: public void addHandler(Handler handler, int index) {
166: if (log.isDebugEnabled()) {
167: log.debug("Handler " + handler.getName()
168: + " inserted at position " + index + " of Phase "
169: + phaseName);
170: }
171: handlers.add(index, handler);
172: }
173:
174: /**
175: * Confirm that all post-conditions of this Phase are met. After all Handlers in a
176: * Phase are invoke()d, this method will be called. Subclasses should override it in order
177: * to confirm that the purpose of the given Phase has been acheived.
178: *
179: * @param msgContext the active MessageContext
180: * @throws AxisFault if a post-condition has not been met, or other problems occur
181: */
182: public void checkPostConditions(MessageContext msgContext)
183: throws AxisFault {
184: // Default version does nothing
185: }
186:
187: /**
188: * Check the preconditions for a Phase. This method will be called when the Phase is
189: * invoked, BEFORE any Handlers are invoked. Subclasses should override it in order
190: * to confirm that necessary preconditions are met before the Phase does its work. They
191: * should throw an appropriate AxisFault if not.
192: *
193: * @param msgContext the active MessageContext
194: * @throws AxisFault if a precondition is not met, or in case of other problem
195: */
196: public void checkPreconditions(MessageContext msgContext)
197: throws AxisFault {
198: // Default version does nothing
199: }
200:
201: public void cleanup() {
202: // Default version does nothing
203: }
204:
205: public void init(HandlerDescription handlerdesc) {
206: // Default version does nothing
207: }
208:
209: private void insertHandler(HandlerDescription handlerDesc)
210: throws PhaseException {
211: Handler handler = handlerDesc.getHandler();
212: PhaseRule rules = handler.getHandlerDesc().getRules();
213: String beforeName = rules.getBefore();
214: String afterName = rules.getAfter();
215:
216: // If we don't care where it goes, tack it on at the end
217: if (beforeName == null && afterName == null) {
218: addHandler(handler);
219: return;
220: }
221:
222: // Otherwise walk the list and find the right place to put it
223: int beforeIndex = -1, afterIndex = -1;
224:
225: for (int i = 0; i < handlers.size(); i++) {
226: Handler tempHandler = (Handler) handlers.get(i);
227:
228: if ((beforeName != null) && (beforeIndex == -1)) {
229: if (tempHandler.getName().equals(beforeName)) {
230: // Found the "before" handler
231: beforeIndex = i;
232: }
233: }
234:
235: if ((afterName != null) && (afterIndex == -1)) {
236: if (tempHandler.getName().equals(afterName)) {
237: // Found the "after" handler
238: afterIndex = i;
239: }
240: }
241: }
242:
243: if ((beforeIndex > -1) && (afterIndex >= beforeIndex)) {
244: throw new PhaseException("Can't insert handler because "
245: + beforeName + " is before " + afterName
246: + " in Phase '" + phaseName + "'");
247: }
248:
249: if (phaseFirstSet && beforeIndex == 0) {
250: throw new PhaseException(
251: "Can't insert handler before handler '"
252: + beforeName
253: + "', which is marked phaseFirst");
254: }
255:
256: if (phaseLastSet && afterIndex == (handlers.size() - 1)) {
257: throw new PhaseException(
258: "Can't insert handler after handler '" + afterName
259: + "', which is marked phaseLast");
260: }
261:
262: if (beforeIndex > -1) {
263: handlers.add(beforeIndex, handler);
264: } else {
265: handlers.add(handler);
266: }
267: }
268:
269: /**
270: * Invoke all the handlers in this Phase
271: *
272: * @param msgctx the current MessageContext
273: * @return An InvocationResponse that indicates what
274: * the next step in the message processing should be.
275: * @throws org.apache.axis2.AxisFault
276: */
277: public final InvocationResponse invoke(MessageContext msgctx)
278: throws AxisFault {
279: boolean isDebugEnabled = LoggingControl.debugLoggingAllowed
280: && log.isDebugEnabled();
281: if (isDebugEnabled) {
282: log.debug(msgctx.getLogIDString()
283: + " Checking pre-condition for Phase \""
284: + phaseName + "\"");
285: }
286:
287: InvocationResponse pi = InvocationResponse.CONTINUE;
288:
289: int currentIndex = msgctx.getCurrentPhaseIndex();
290:
291: if (currentIndex == 0) {
292: checkPreconditions(msgctx);
293: }
294:
295: if (isDebugEnabled) {
296: log.debug(msgctx.getLogIDString() + " Invoking phase \""
297: + phaseName + "\"");
298: }
299:
300: while (currentIndex < handlers.size()) {
301: Handler handler = (Handler) handlers.get(currentIndex);
302:
303: if (isDebugEnabled) {
304: log.debug(msgctx.getLogIDString()
305: + " Invoking Handler '" + handler.getName()
306: + "' in Phase '" + phaseName + "'");
307: }
308: pi = handler.invoke(msgctx);
309:
310: if (!pi.equals(InvocationResponse.CONTINUE)) {
311: return pi;
312: }
313:
314: currentIndex++;
315: msgctx.setCurrentPhaseIndex(currentIndex);
316: }
317:
318: if (isDebugEnabled) {
319: log.debug(msgctx.getLogIDString()
320: + " Checking post-conditions for phase \""
321: + phaseName + "\"");
322: }
323:
324: msgctx.setCurrentPhaseIndex(0);
325: checkPostConditions(msgctx);
326: return pi;
327: }
328:
329: public void flowComplete(MessageContext msgContext) {
330: boolean isDebugEnabled = LoggingControl.debugLoggingAllowed
331: && log.isDebugEnabled();
332: if (isDebugEnabled) {
333: log.debug(msgContext.getLogIDString()
334: + " Invoking flowComplete() in Phase \""
335: + phaseName + "\"");
336: }
337:
338: // This will be non-zero if we failed during execution of one of the
339: // handlers in this phase
340: int currentHandlerIndex = msgContext.getCurrentPhaseIndex();
341: if (currentHandlerIndex == 0) {
342: currentHandlerIndex = handlers.size();
343: } else {
344: /*We need to set it to 0 so that any previous phases will execute all
345: * of their handlers.*/
346: msgContext.setCurrentPhaseIndex(0);
347: }
348:
349: for (; currentHandlerIndex > 0; currentHandlerIndex--) {
350: Handler handler = (Handler) handlers
351: .get(currentHandlerIndex - 1);
352:
353: if (isDebugEnabled) {
354: log.debug(msgContext.getLogIDString()
355: + " Invoking flowComplete() for Handler '"
356: + handler.getName() + "' in Phase '"
357: + phaseName + "'");
358: }
359:
360: handler.flowComplete(msgContext);
361: }
362: }
363:
364: public String toString() {
365: return this .getPhaseName();
366: }
367:
368: public int getHandlerCount() {
369: return handlers.size();
370: }
371:
372: public HandlerDescription getHandlerDesc() {
373: return null;
374: }
375:
376: /**
377: * Gets all the handlers in the phase.
378: *
379: * @return Returns an ArrayList of Handlers
380: */
381: public ArrayList getHandlers() {
382: return handlers;
383: }
384:
385: public String getName() {
386: return phaseName;
387: }
388:
389: public Parameter getParameter(String name) {
390: return null;
391: }
392:
393: /**
394: * @return Returns the name.
395: */
396: public String getPhaseName() {
397: return phaseName;
398: }
399:
400: public void setName(String phaseName) {
401: this .phaseName = phaseName;
402: }
403:
404: /**
405: * Add a Handler to the Phase in the very first position, and ensure no other Handler
406: * will come before it.
407: *
408: * @param handler the Handler to add
409: * @throws PhaseException if another Handler is already set as phaseFirst
410: */
411: public void setPhaseFirst(Handler handler) throws PhaseException {
412: if (phaseFirstSet) {
413: throw new PhaseException(
414: "PhaseFirst has been set already, cannot have two"
415: + " phaseFirst Handlers for Phase '"
416: + this .getPhaseName() + "'");
417: }
418: handlers.add(0, handler);
419: phaseFirstSet = true;
420: }
421:
422: /**
423: * Add a Handler to the Phase in the very last position, and ensure no other Handler
424: * will come after it.
425: *
426: * @param handler the Handler to add
427: * @throws PhaseException if another Handler is already set as phaseLast
428: */
429: public void setPhaseLast(Handler handler) throws PhaseException {
430: if (phaseLastSet) {
431: throw new PhaseException(
432: "PhaseLast already has been set,"
433: + " cannot have two PhaseLast Handler for same phase "
434: + this .getPhaseName());
435: }
436:
437: handlers.add(handler);
438: phaseLastSet = true;
439: }
440:
441: /**
442: * Remove a given Handler from a phase using a HandlerDescription
443: *
444: * @param handlerDesc the HandlerDescription to remove
445: */
446: public void removeHandler(HandlerDescription handlerDesc) {
447: if (handlers.remove(handlerDesc.getHandler())) {
448: PhaseRule rule = handlerDesc.getRules();
449: if (rule.isPhaseFirst()) {
450: phaseFirstSet = false;
451: }
452: if (rule.isPhaseLast()) {
453: phaseLastSet = false;
454: }
455: if (rule.isPhaseFirst() && rule.isPhaseLast()) {
456: isOneHandler = false;
457: }
458: log.debug("removed handler " + handlerDesc.getName()
459: + " from the phase " + phaseName);
460: } else {
461: log.debug("unable to remove handler "
462: + handlerDesc.getName() + " from the phase "
463: + phaseName);
464: }
465: }
466:
467: }
|