| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.axis ; |
| |
| import org.apache.axis.components.logger.LogFactory; |
| import org.apache.axis.handlers.BasicHandler; |
| import org.apache.axis.strategies.InvocationStrategy; |
| import org.apache.axis.strategies.WSDLGenStrategy; |
| import org.apache.axis.utils.Messages; |
| import org.apache.commons.logging.Log; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| import javax.xml.namespace.QName; |
| import java.util.Enumeration; |
| import java.util.Vector; |
| |
| /** |
| * A Simple Chain is a 'composite' Handler in that it aggregates a collection |
| * of Handlers and also acts as a Handler which delegates its operations to |
| * the collection. |
| * <p> |
| * A Simple Chain initially has no Handlers. Handlers may be added until the |
| * chain is invoke()d after which Handlers may not be added (and any attempt |
| * to do so will throw an exception). |
| * |
| * @author Doug Davis (dug@us.ibm.com) |
| * @author Glyn Normington (norm@uk.ibm.com) |
| */ |
| public class SimpleChain extends BasicHandler implements Chain { |
| private static Log log = |
| LogFactory.getLog(SimpleChain.class.getName()); |
| |
| protected Vector handlers = new Vector(); |
| protected boolean invoked = false; |
| |
| private String CAUGHTFAULT_PROPERTY = |
| "org.apache.axis.SimpleChain.caughtFaultInResponse"; |
| |
| public void init() { |
| for ( int i = 0 ; i < handlers.size() ; i++ ) |
| ((Handler) handlers.elementAt( i )).init(); |
| } |
| |
| public void cleanup() { |
| for ( int i = 0 ; i < handlers.size() ; i++ ) |
| ((Handler) handlers.elementAt( i )).cleanup(); |
| } |
| |
| private static final HandlerIterationStrategy iVisitor = |
| new InvocationStrategy(); |
| |
| private static final HandlerIterationStrategy wsdlVisitor = |
| new WSDLGenStrategy(); |
| |
| /** |
| * Iterate over the chain invoking each handler. If there's a fault |
| * then call 'onFault' for each completed handler in reverse order, then |
| * rethrow the exception. |
| * |
| * @throws AxisFault if there was a fault with any of the handlers |
| */ |
| public void invoke(MessageContext msgContext) throws AxisFault { |
| if (log.isDebugEnabled()) { |
| log.debug("Enter: SimpleChain::invoke"); |
| } |
| |
| invoked = true; |
| doVisiting(msgContext, iVisitor); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Exit: SimpleChain::invoke"); |
| } |
| } |
| |
| /** |
| * Iterate over the chain letting each handler have a crack at |
| * contributing to a WSDL description. |
| * |
| * @param msgContext the <code>MessageContext</code> to write the WSDL |
| * out to |
| * @throws AxisFault if there was a problem writing the WSDL |
| */ |
| public void generateWSDL(MessageContext msgContext) throws AxisFault { |
| if (log.isDebugEnabled()) { |
| log.debug("Enter: SimpleChain::generateWSDL"); |
| } |
| |
| invoked = true; |
| doVisiting(msgContext, wsdlVisitor); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Exit: SimpleChain::generateWSDL"); |
| } |
| } |
| |
| private void doVisiting(MessageContext msgContext, |
| HandlerIterationStrategy visitor) throws AxisFault { |
| int i = 0 ; |
| try { |
| Enumeration enumeration = handlers.elements(); |
| while (enumeration.hasMoreElements()) { |
| Handler h = (Handler)enumeration.nextElement(); |
| visitor.visit(h, msgContext); |
| i++; |
| } |
| } catch( AxisFault f ) { |
| // Something went wrong. If we haven't already put this fault |
| // into the MessageContext's response message, do so and make sure |
| // we only do it once. This allows onFault() methods to safely |
| // set headers and such in the response message without them |
| // getting stomped. |
| if (!msgContext.isPropertyTrue(CAUGHTFAULT_PROPERTY)) { |
| // Attach the fault to the response message; enabling access to the |
| // fault details while inside the handler onFault methods. |
| Message respMsg = new Message(f); |
| msgContext.setResponseMessage(respMsg); |
| msgContext.setProperty(CAUGHTFAULT_PROPERTY, Boolean.TRUE); |
| } |
| while( --i >= 0 ) |
| ((Handler) handlers.elementAt( i )).onFault( msgContext ); |
| throw f; |
| } |
| } |
| |
| /** |
| * Notify the handlers in this chain because some handler |
| * later on has faulted - in reverse order. If any handlers |
| * have been added since we visited the chain, they will get |
| * notified too! |
| * |
| * @param msgContext the context to process |
| */ |
| public void onFault(MessageContext msgContext) { |
| if (log.isDebugEnabled()) { |
| log.debug("Enter: SimpleChain::onFault"); |
| } |
| |
| for ( int i = handlers.size()-1 ; i >= 0 ; i-- ) |
| ((Handler) handlers.elementAt( i )).onFault( msgContext ); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Exit: SimpleChain::onFault"); |
| } |
| } |
| |
| public boolean canHandleBlock(QName qname) { |
| for ( int i = 0 ; i < handlers.size() ; i++ ) |
| if ( ((Handler) handlers.elementAt( i )).canHandleBlock(qname) ) |
| return( true ); |
| return( false ); |
| } |
| |
| public void addHandler(Handler handler) { |
| if (handler == null) |
| throw new InternalException( |
| Messages.getMessage("nullHandler00", |
| "SimpleChain::addHandler")); |
| |
| if (invoked) |
| throw new InternalException( |
| Messages.getMessage("addAfterInvoke00", |
| "SimpleChain::addHandler")); |
| |
| handlers.add( handler ); |
| } |
| |
| public boolean contains(Handler handler) { |
| return( handlers.contains( handler )); |
| } |
| |
| public Handler[] getHandlers() { |
| if (handlers.size() == 0) |
| return null; |
| |
| Handler [] ret = new Handler[handlers.size()]; |
| return( (Handler[]) handlers.toArray(ret) ); |
| } |
| |
| public Element getDeploymentData(Document doc) { |
| if (log.isDebugEnabled()) { |
| log.debug( Messages.getMessage("enter00", |
| "SimpleChain::getDeploymentData") ); |
| } |
| |
| Element root = doc.createElementNS("", "chain" ); |
| |
| StringBuffer str = new StringBuffer(); |
| int i = 0; |
| while (i < handlers.size()) { |
| if ( i != 0 ) str.append(","); |
| Handler h = (Handler) handlers.elementAt(i); |
| str.append( h.getName() ); |
| i++; |
| } |
| if (i > 0) { |
| root.setAttribute( "flow", str.toString() ); |
| } |
| |
| if ( options != null ) { |
| Enumeration e = options.keys(); |
| while ( e.hasMoreElements() ) { |
| String k = (String) e.nextElement(); |
| Object v = options.get(k); |
| Element e1 = doc.createElementNS("", "option"); |
| e1.setAttribute( "name", k ); |
| e1.setAttribute( "value", v.toString() ); |
| root.appendChild( e1 ); |
| } |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Exit: SimpleChain::getDeploymentData"); |
| } |
| |
| return( root ); |
| } |
| } |