org.apache.axis.SimpleChain.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.axis.SimpleChain.java

Source

/*
 * 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);
    }
}