Package org.apache.muse.core.routing

Source Code of org.apache.muse.core.routing.ReflectionMessageHandler

/*=============================================================================*
*  Copyright 2006 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.muse.core.routing;

import java.lang.reflect.Method;

import javax.xml.namespace.QName;

import org.w3c.dom.Element;

import org.apache.muse.core.serializer.Serializer;
import org.apache.muse.core.serializer.SerializerRegistry;
import org.apache.muse.util.messages.Messages;
import org.apache.muse.util.messages.MessagesFactory;
import org.apache.muse.util.xml.XmlUtils;
import org.apache.muse.ws.addressing.soap.SoapFault;

/**
*
* ReflectionMessageHandler is a generic implementation of
* {@linkplain org.apache.muse.core.routing.MessageHandler MessageHandler}
* that can be applied to any Java method. It uses reflection to determine
* what types are being used by a method signature and then invokes the
* {@linkplain Serializer Serializers} that have been registered with Muse
* to do the XML/POJO transformations. If a method references a type that is
* not included in Muse's set of built-in Serializers, you must register a
* Serializer for that type in order to take advantage of this class.
* <br><br>
* Muse uses this class by default if no MessageHandler is specified for
* a user-defined operation. Application initialization will fail if this
* default is specified but no Serializer is provided for a user-defined type.
* You can add custom MessageHandlers to your own capabilities programmatically
* using the Capability.setMessageHandlers() method.
*
* @author Dan Jemiolo (danj)
*
*/

public class ReflectionMessageHandler extends AbstractMessageHandler
{
    //
    // Used to lookup all exception messages
    //
    private static Messages _MESSAGES =
        MessagesFactory.get(ReflectionMessageHandler.class);
   
    private QName _returnValueName = null;
   
    public ReflectionMessageHandler(String actionURI,
                                    QName requestQName,
                                    QName returnValueName)
    {
        super(actionURI, requestQName);
        _returnValueName = returnValueName;
    }
   
    /**
     *
     * {@inheritDoc}
     * <br><br>
     * This implementation uses the MessageHandler's java.lang.reflect.Method
     * to discover what parameter types can be expected in the given Element.
     * It then looks up the Serializers and uses them to deserialize the child
     * Elements in order.
     * <br><br>
     * If the Element has no child elements but has text content, <b>and</b>
     * the method has one parameter, the given Element is parsed as though it
     * were the parameter.
     *
     */
    public Object[] fromXML(Element xml)
        throws SoapFault
    {
        Method method = getMethod();
       
        if (method == null)
            throw new IllegalStateException(_MESSAGES.get("NoMethod"));
       
        if (xml == null)
            return EMPTY_REQUEST;
       
        Class[] parameters = method.getParameterTypes();
        Object[] objects = new Object[parameters.length];
       
        Element[] elements = XmlUtils.getAllElements(xml);
       
        //
        // special cases where the method only takes one parameter:
        //
        // 1. there is no child element, so we hope there is a simple (text)
        //    value in the root element
        //
        // OR
        //
        // 2. the parameter type is array, so we treat all child elements
        //    as members of the array
        //
        if (parameters.length == 1 &&
            (elements.length == 0 || parameters[0].isArray()))
            elements = new Element[]{ xml };
       
        //
        // make sure we have the correct number of parameter values
        //
        if (elements.length != parameters.length)
        {
            Object[] filler = {
                method.getName(), new Integer(parameters.length), new Integer(elements.length)       
            };
            throw new SoapFault(_MESSAGES.get("IncorrectParams", filler));
        }

        SerializerRegistry registry = SerializerRegistry.getInstance();
       
        //
        // general case: apply appropriate serializer to each child element
        //
        for (int i = 0; i < elements.length; ++i)
        {
            Serializer ser = registry.getSerializer(parameters[i]);
            objects[i] = ser.fromXML(elements[i]);
        }
       
        return objects;
    }
   
    protected QName getReturnValueName()
    {
        return _returnValueName;
    }
   
    /**
     *
     * {@inheritDoc}
     * <br><br>
     * This implementation uses the MessageHandler's java.lang.reflect.Method
     * to discover what return type can be expected in the given Element. It
     * then looks up the Serializer and uses it to serialize the object.
     *
     */
    public Element toXML(Object result)
        throws SoapFault
    {
        Method method = getMethod();
       
        if (method == null)
            throw new IllegalStateException(_MESSAGES.get("NoMethod"));
       
        Class returnType = method.getReturnType();
       
        //
        // void methods -> empty element
        //
        if (returnType == Void.TYPE)
            return XmlUtils.createElement(getResponseName());
       
        //
        // for all non-void methods, we need to find the serializer
        // for the return type, then determine if it's an array and
        // deal with it accordingly
        //
        SerializerRegistry registry = SerializerRegistry.getInstance();
        Serializer ser = registry.getSerializer(returnType);
       
        QName returnValueName = getReturnValueName();
        QName responseBodyName = getResponseName();
        boolean isComplex = true;
       
        //
        // for many simple return types, we just embed the value in
        // the body's response element
        //
        if (returnValueName == null)
        {
            isComplex = false;
            returnValueName = responseBodyName;
        }
       
        //
        // for complex types, we need a child element under the
        // response body element
        //
        Element responseXML = XmlUtils.createElement(responseBodyName);
        Element valueXML = ser.toXML(result, returnValueName);
       
        //
        // for arrays, we put the children (array items) under the
        // response body element
        //
        if (returnType.isArray())
            XmlUtils.moveSubTree(valueXML, responseXML);
       
        else if (isComplex)
            responseXML.appendChild(valueXML);
       
        else
            responseXML = valueXML;
       
        return responseXML;
    }
}
TOP

Related Classes of org.apache.muse.core.routing.ReflectionMessageHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.