Package org.jboss.soa.esb.actions.converters

Source Code of org.jboss.soa.esb.actions.converters.XStreamToObject

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.soa.esb.actions.converters;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.apache.log4j.Logger;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.actions.ActionProcessingException;
import org.jboss.soa.esb.actions.ActionUtils;
import org.jboss.soa.esb.actions.converters.xstream.conf.FieldAliasConf;
import org.jboss.soa.esb.actions.converters.xstream.conf.ImplicitCollectionConf;
import org.jboss.soa.esb.actions.converters.xstream.conf.XStreamConfigurator;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.helpers.KeyValuePair;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import org.jboss.soa.esb.message.body.content.BytesBody;
import org.jboss.soa.esb.util.ClassUtil;
import org.jboss.soa.esb.util.XPathUtil;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.DomReader;


/**
* XML to Object processor that uses Uses the <a href="http://xstream.codehaus.org/">XStream</a> .
* <p/>
* Sample Action Configuration:
* <pre>{@code
* <action name="doCustomer" class="XStreamObject">
*     <property name="class-alias" value="Customer"/>
*     <property name="incoming-type" value="CustomerProcessor"/>
*     <property name="exclude-package" value="false"/>
*     <property name="root-node" value="/root/Customer"/>
*     <property name="aliases">
*     <alias name="aliasName" class="className" />
*     <alias name="aliasName" class="className" />
*     ...
*     </property>
*     <property name="fieldAliases">
*     <field-alias alias="aliasName" class="className" fieldName="fieldName"/>
*     <field-alias alias="aliasName" class="className" fieldName="fieldName"/>
*     ...
*     </property>
*     <property name="attributeAliases">
*     <attribute-alias name="aliasName" class="className"/>
*     <attribute-alias name="aliasName" class="className"/>
*     ...
*     </property>
*     <property name="implicit-collections">
*     <implicit-collection class="className" fieldName="fieldName" fieldType="java.lang.String" />
*     <implicit-collection class="className" fieldName="fieldName" fieldType="java.lang.Integer"/>
*     ...
*     </property>
*     <property name="converters">
*     <converter class="className" />
*     <converter class="className" />
*     ...
* </action>
* }</pre>
* <p/>
* <lu>
* <li><i>class-alias</i> Optional. Class alias for the 'incoming-type'.</li>
* <li><i>incoming-type</i> Required. Class of the incoming type.</li>
* <li><i>exclude-package-type</i> Optional, defaults to true. Determines whether package name should be removed from the incoming type.</li>
* <li><i>root-node</i> Optional. Specifies an XPath expression to be used to determine the root node that XStream will use.</li>
* <li><i>aliases</i> Optional. Specifies extra class aliases.</li>
* <li><i>fieldAliases</i> Optional. Specifies field aliases.</li>
* <li><i>implicit-collections</i> Optional. Specifies implicit collections which are when you have an xml element that is a place holder for a collection of other elements.
*                                 In this case you are telling XStream to not include the holder element but instead place its element into the the 'fieldName' in the target class.
*                                 'className' is the collection type.
*                                 'fieldType' is the type the elements in the collection.</li>
* <li><i>converters</i> Optional. Specifies converters that will be registered with XStream.</li>
* </lu>
*
* The XML root element is either set from the "class-alias" property or the classes full name.  In the later case, the class package is
* excluded unless "exclude-package" is set to "false"/"no".
*
* @author danielmarchant
* @author Daniel Bevenius
* @since Version 4.0
*/
public class XStreamToObject extends AbstractObjectXStream {

  private static Logger logger = Logger.getLogger(XStreamToObject.class);
 
    // class related variables
    private Class<?> incomingType;
   
    // action related variables
    private Map<String,String> aliases;
    private Map<String,String> attributeAliases;
  private List<FieldAliasConf> fieldAliases;
  private List<String> converters;
  private List<ImplicitCollectionConf> implicitCollections;
    private MessagePayloadProxy payloadProxy;
   

    /**
     * Public constructor.
     * @param properties Action Properties.
     * @throws ConfigurationException Action not properly configured.
     */
    public XStreamToObject(ConfigTree properties) {
      this(properties.getName(), properties.attributesAsList());
      XStreamConfigurator xstreamConfig = new XStreamConfigurator(properties);
      aliases = getAliases( properties, "alias" );
      fieldAliases = xstreamConfig.getFieldAliases();
      attributeAliases = getAliases( properties, "attribute-alias" );
      converters = getConverters( properties, "converter" );
      implicitCollections = xstreamConfig.getImplicitCollections();
        payloadProxy = new MessagePayloadProxy(properties,
                                               new String[] {BytesBody.BYTES_LOCATION, ActionUtils.POST_ACTION_DATA},
                                               new String[] {ActionUtils.POST_ACTION_DATA});
    }
   
    /**
     * Public constructor.
     * @param actionName Action name.
     * @param properties Action Properties.
     * @throws ConfigurationException Action not properly configured.
     */
    protected XStreamToObject(String actionName, List<KeyValuePair> properties) {
      super(actionName,properties);
      String incomingTypeStr = KeyValuePair.getValue("incoming-type", properties);
      try {
      incomingType = ClassUtil.forName(incomingTypeStr, getClass());
    } catch (ClassNotFoundException e) {
      logger.error("Could not find : " + incomingTypeStr,e);
    }
    }
 
  /**
   * Processes the message by using the giving class-processor.
   * 
   */
  public Message process(Message message) throws ActionProcessingException {
        Object object;

        try {
            object = payloadProxy.getPayload(message);
        } catch (MessageDeliverException e) {
            throw new ActionProcessingException(e);
        }

        try {
      Object toObject = incomingType.newInstance();
      toObject = fromXmlToObject( object.toString(), toObject );
     
      payloadProxy.setPayload(message, toObject);
    } catch (InstantiationException e) {
      logger.error( e );
      throw new ActionProcessingException("Could not invoke for Arg: " + getName(),e );
    } catch (IllegalAccessException e) {
      logger.error( e );
      throw new ActionProcessingException("Could not access for Arg: " + getName(),e );
    } catch (MessageDeliverException e) {
            throw new ActionProcessingException(e);
        }

        return message;
  }
 
  /**
   * Will extract the alias elements from the passed-in conifgTree
   *
   * @param configTree      the configuration for this class
   *
   * @return Map<String,String>   either an empty map or a map containing the alias name
   *                 as its key and the corresponding value is the class to map
   *                 it to. 
   */
  protected Map<String,String> getAliases( final ConfigTree configTree, final String childName)
  {
        Map<String,String> aliases = new HashMap<String,String>();
   
    ConfigTree[] children = configTree.getChildren( childName );
   
    if ( children != null ) {
      for ( ConfigTree alias : children )
        aliases.put( alias.getAttribute( "name" ), alias.getAttribute( "class" ) );
    }
    return aliases;
   
  }
 
  /**
     * Will extract the alias elements from the passed-in conifgTree
     *
     * @param configTree            the configuration for this class
     *
     * @return Map<String,String>   either an empty map or a map containing the alias name
     *                              as its key and the corresponding value is the class to map
     *                              it to. 
     */
    protected List<FieldAliasConf> getFieldAliases( final ConfigTree configTree, final String childName)
    {
        List<FieldAliasConf> aliases = new ArrayList<FieldAliasConf>();
       
        ConfigTree[] children = configTree.getChildren( childName );
       
        if ( children != null )
        {
            for ( ConfigTree alias : children )
            {
                aliases.add(new FieldAliasConf(alias.getAttribute("alias"), alias.getAttribute("class"), alias.getAttribute("fieldName")));
            }
        }
        return aliases;
    }
   
  /**
   * Will extract the converter elements from the passed-in conifgTree
   *
   * @param configTree      the configuration for this class
   *
   * @return Map<String,String>   either an empty map or a map containing the converter class
   */
  protected List<String> getConverters( final ConfigTree configTree, final String childName )
  {
    List<String> converters = new ArrayList<String>();
   
    ConfigTree[] children = configTree.getChildren( childName );
   
    if ( children != null ) {
      for ( ConfigTree converter : children )
        converters.add( converter.getAttribute( "class" ) );
   
    return converters;
  }

  /**
     * Added the aliases contained in the passed-in map to the
     * passed-in XStream object
     *
     * @param aliases    Map of aliases.
     * @throws ActionProcessingException
     */
    protected void addAliases( Map<String, String> aliases, XStream xstream) throws ActionProcessingException
    {
        if ( aliases == null )
            return;
       
        Set<Map.Entry<String,String>> set = aliases.entrySet();
        for (Map.Entry me : set ) {
            String className = (String) me.getValue();
            try {
                Class<?> clazz = ClassUtil.forName( className, getClass() );
                xstream.alias((String)me.getKey(), clazz );
            } catch (ClassNotFoundException e) {
                logger.error("ClassNotFoundException: ", e);
                throw new ActionProcessingException("Could not add alias : " + (String)me.getKey() + ", class : " + className ,e );
            }
        }
    }
 
  /**
   * Registers the converters contained in the passed in list
   *
   * @param converters which should be registered with XStream
   * @param xstream
   * @throws ActionProcessingException
   */
  protected void addConverters( List<String> converters, XStream xstream) throws ActionProcessingException
  {
    if ( converters == null )
      return;
   
    for( String converterClass : converters )
    {
      if ( converterClass == null )
        continue;
      try {
        Class<?> clazz = ClassUtil.forName( converterClass, getClass() );
            xstream.registerConverter((Converter)clazz.newInstance());
           
      } catch (ClassNotFoundException e) {
        logger.error("ClassNotFoundException: ", e);
        throw new ActionProcessingException("Could not register converter : " + converterClass.getClass().getName(),e );
      } catch (InstantiationException e)
      {
        logger.error("InstantiationException: ", e);
      } catch (IllegalAccessException e)
      {
        logger.error("IllegalAccessException: ", e);
      }
     
    }
  }
 
  /**
   * Added the aliases contained in the passed-in map to the
   * passed-in XStream object
   *
   * @param aliases   Map of aliases.
   * @throws ActionProcessingException
   */
  protected void addAttributeAliases( Map<String, String> aliases, XStream xstream) throws ActionProcessingException
  {
    if ( aliases == null )
      return;
   
    Set<Map.Entry<String,String>> set = aliases.entrySet();
    for (Map.Entry me : set ) {
      String className = (String) me.getValue();
      try {
        Class<?> clazz = ClassUtil.forName( className, getClass() );
            xstream.useAttributeFor( (String)me.getKey(), clazz );
      } catch (ClassNotFoundException e) {
        logger.error("ClassNotFoundException: ", e);
        throw new ActionProcessingException("Could not add alias : " + (String)me.getKey() + ", class : " + className ,e );
      }
    }
  }
 
  /**
   *
   * @param xml    the xml String
   * @param root    an instance of the type of the root element
   * @throws ActionProcessingException
   * @throws ParserConfigurationException
   * @throws IOException
   * @throws SAXException
   */
  protected Object fromXmlToObject(String xml, Object root ) throws ActionProcessingException
  {
    HierarchicalStreamReader reader = null;
    try
    {
      reader = new DomReader( getRootElement( xml, rootNodeName ) );
       
          XStream xstream = new XStream( new DomDriver() );
          xstream.alias(getAlias(incomingType), incomingType);
          addAliases( aliases, xstream );
            XStreamConfigurator.addFieldAliases(fieldAliases, xstream);
          addAttributeAliases( attributeAliases, xstream );
          addConverters( converters, xstream );
            XStreamConfigurator.addImplicitCollections(implicitCollections, xstream);
      return xstream.unmarshal( reader, root );
    }
    finally
    {
      if ( reader != nullreader.close();
    }
  }

  /*
   * Simply delegates to XPathUtil and catches exceptions specific
   * to that class and rethrows an ActionProcessingException
   */
  private Element getRootElement( String xml, String xPathExpression ) throws ActionProcessingException
  {
    try
    {
      return XPathUtil.getNodeFromXPathExpression( xml, xPathExpression );
    }
    catch (ParserConfigurationException e)
    {
      logger.error( "ParserConfigurationException:", e );
      throw new ActionProcessingException( e );
    }
    catch (SAXException e)
    {
      logger.error( "SAXException : ", e );
      throw new ActionProcessingException( e );
    }
    catch (IOException e)
    {
      logger.error( "IOException: ", e );
      throw new ActionProcessingException( e );
    }
    catch (XPathExpressionException e)
    {
      logger.error( "XPathExpressionException", e );
      throw new ActionProcessingException( e );
    }
  }
}
TOP

Related Classes of org.jboss.soa.esb.actions.converters.XStreamToObject

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.