Package org.apache.ws.util.helper

Source Code of org.apache.ws.util.helper.Saaj2StringConverter

/*=============================================================================*
*  Copyright 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.ws.util.helper;

import org.apache.ws.util.XmlConstants;
import org.apache.ws.util.i18n.Keys;
import org.apache.ws.util.i18n.Messages;
import org.apache.ws.util.i18n.MessagesImpl;

import javax.xml.soap.Name;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.Text;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**       LOG-DONE
* @author Ian P. Springer (Hewlett-Packard Company)
*/
public class Saaj2StringConverter
{
   public static final Messages MSG = MessagesImpl.getInstance();
   /**
    * Whitespace string to use for indentation in {@link #toString( javax.xml.soap.Node )}.
    */
   private static final String DEFAULT_NODE_INDENT_STRING = "  ";

   /**
    * The string to use for each indent (may only contain spaces or tabs).
    */
   private String m_indent_str = DEFAULT_NODE_INDENT_STRING;

   /**
    * Given a {@link SOAPElement}, returns a list containing the children of that element. If at least one of the
    * children is a SOAPElement, any {@link Text} nodes are excluded from the list. This is because it is assumed that
    * if the specified element has mixed content, it is only because of insignificant whitespace text nodes.
    *
    * @param soap_elem a SAAJ {@link SOAPElement}
    *
    * @return a list containing the children of the specified {@link SOAPElement}
    */
   public static List getChildNodes( SOAPElement soap_elem )
   {
      List     elem_children = new ArrayList(  );
      List     text_children = new ArrayList(  );
      Iterator node_iter     = soap_elem.getChildElements(  );

      while ( node_iter.hasNext(  ) )
      {
         Node child_node = (Node) node_iter.next(  );

         if ( isSOAPElement( child_node ) )
         {
            elem_children.add( child_node );
         }
         else
         {
            text_children.add( child_node );
         }
      }

      return ( elem_children.isEmpty(  ) ? text_children : elem_children );
   }

   /**
    * @param soap_elem
    * @param ns_uri
    *
    * @return
    */
   public static String getDeclaredPrefix( SOAPElement soap_elem,
                                           String      ns_uri )
   {
      Iterator prefixes = soap_elem.getNamespacePrefixes(  );

      while ( prefixes.hasNext(  ) )
      {
         String prefix = (String) prefixes.next(  );

         if ( soap_elem.getNamespaceURI( prefix ).equals( ns_uri ) )
         {
            return ( prefix );
         }
      }

      return ( null );
   }

   /**
    * Sets the indent string.
    *
    * @param indent_str the indent string to use; if null, indenting will be disabled
    */
   public void setIndentString( String indent_str )
   {
      m_indent_str = indent_str;
   }

   /**
    * Gets the indent string.
    *
    * @return the indent string being used; if null, indenting is disabled
    */
   public String getIndentString(  )
   {
      return m_indent_str;
   }

   /**
    * Returns true if the specified SAAJ node is an element, or false otherwise.
    *
    * @param soap_node a SAAJ node
    *
    * @return true if the specified SAAJ node is an element, or false otherwise
    */
   public static boolean isSOAPElement( Node soap_node )
   {
      // NOTE: the second condition below is nessary for Axis, because its Text impl also implements SOAPElement
      return ( soap_node instanceof SOAPElement && !( soap_node instanceof Text ) );
   }

   /**
    * DOCUMENT_ME
    *
    * @param soap_text DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    *
    * @throws SOAPException DOCUMENT_ME
    */
   public static String getValue( Text soap_text )
   throws SOAPException
   {
      if ( soap_text == null )
      {
         throw new IllegalArgumentException( MSG.getMessage( Keys.NULL_PARAM_NOT_ALLOWED) );
      }

      String value = soap_text.getValue(  );

      if ( value == null )
      {
         value = soap_text.toString(  );
      }

      if ( value == null )
      {
         throw new SOAPException( MSG.getMessage( Keys.NULL_VALUE) );
      }

      return ( value );
   }

   /**
    * Returns true if the specified string is non-null and does not equal ""; otherwise returns false.
    *
    * @param str a string
    *
    * @return true if the specified string is non-null and does not equal ""; otherwise false
    */
   public static boolean hasNonEmptyValue( String str )
   {
      return ( ( str != null ) && !str.equals( "" ) );
   }

   /**
    * Returns a string representation of the specified {@link javax.xml.soap.Node}.
    *
    * @param soap_node a SAAJ SOAP node
    *
    * @return a string represntation of the SOAP node
    *
    * @throws SOAPException
    */
   public String toString( Node soap_node )
   throws SOAPException
   {
      return ( buildSOAPNodeStringBuffer( new StringBuffer(  ),
                                          soap_node,
                                          soap_node,
                                          0 ).toString(  ) );
   }

   /**
    * @param soap_elem a SOAP element
    *
    * @return an Iterator of the element's children
    */
   private static Iterator getChildren( SOAPElement soap_elem )
   {
      List children = null;

      // NOTE (ips, 08/12/03): the below block is a workaround for a bug in AXIS 1.1...
      if ( soap_elem instanceof SOAPEnvelope && false )
      {
         children = getEnvelopeChildren( soap_elem );
      }

      if ( ( children == null ) || children.isEmpty(  ) )
      {
         children = getChildNodes( soap_elem );
      }

      return ( children.iterator(  ) );
   }

   /**
    * DOCUMENT_ME
    *
    * @param current_soap_node DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   private static boolean isElement( Node current_soap_node )
   {
      return !( current_soap_node instanceof Text );
   }

   /**
    * DOCUMENT_ME
    *
    * @param soap_elem DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   private static List getEnvelopeChildren( SOAPElement soap_elem )
   {
      List children;

      children = new ArrayList(  );

      SOAPEnvelope soap_env = (SOAPEnvelope) soap_elem;
      SOAPHeader   header = null;
      SOAPBody     body   = null;

      try
      {
         header    = soap_env.getHeader(  );
         body      = soap_env.getBody(  );
      }
      catch ( SOAPException soape )
      {
         //LOG.warn( ResourceKeys.MSG.getMsg( ResourceKeys.EX_FAILED_TO_GET_SOAP_BODY, soape ) );
      }

      if ( ( header != null ) && ( body != null ) )
      {
         children.add( header );
         children.add( body );
      }

      return children;
   }

   /**
    * DOCUMENT_ME
    *
    * @param pqname         DOCUMENT_ME
    * @param root_soap_elem DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   private static String getPrefix( Name        pqname,
                                    SOAPElement root_soap_elem )
   {
      String prefix = pqname.getPrefix(  );

      if ( ( prefix != null ) && !prefix.equals( "" ) )
      {
         return ( prefix );
      }

      return ( recursiveGetPrefix( pqname, root_soap_elem ) );
   }

   /**
    * @param child
    * @param ns_uri
    *
    * @return
    */
   private static String getPrefix( SOAPElement child,
                                    String      ns_uri )
   {
      if ( child == null )
      {
         //throw new IllegalArgumentException( ResourceKeys.MSG.getMsg( ResourceKeys.EX_SOAP_ELEM_NULL ) );
      }

      String prefix;

      if ( Node.TEXT_NODE == child.getNodeType(  ) )
      {
         return null;
      }

      Name child_name = child.getElementName(  );

      if ( child_name == null )
      {
         return null;
      }

      String child_uri = child_name.getURI(  );

      if ( child_uri == null )
      {
         return null;
      }

      if ( ns_uri == null )
      {
         return null;
      }

      if ( child_uri.equals( ns_uri ) )
      {
         prefix = child.getElementName(  ).getPrefix(  );

         if ( ( prefix != null ) && !prefix.equals( "" ) )
         {
            return ( prefix );
         }
      }

      prefix = getDeclaredPrefix( child, ns_uri );

      if ( ( prefix != null ) && !prefix.equals( "" ) )
      {
         return ( prefix );
      }

      return ( null );
   }

   /**
    * Constructs a string representation of the specified SAAJ {@link Name}.
    *
    * @param pqname a prefixed qname
    *
    * @return a string representation of the prefixed qname
    */
   private static String nameToString( Name pqname )
   {
      if ( pqname == null )
      {
         //LOG.debug( ResourceKeys.MSG.getMsg( ResourceKeys.EX_PASSED_IN_NAME_OBJ_NULL ) );
         return ( "" );
      }

      String prefix     = pqname.getPrefix(  );
      String local_name = pqname.getLocalName(  );

      if ( ( local_name == null ) || local_name.equals( "" ) )
      {
         //LOG.debug( ResourceKeys.MSG.getMsg( ResourceKeys.EX_PASSED_IN_NAME_OBJ_NULL_LOCAL ) );
         if ( ( ( prefix != null ) && !prefix.equals( "" ) ) )
         {
            // NOTE (ips): This is a workaround for a bug in AXIS 1.1's MessageElement.getNamespacePrefixes()
            return ( prefix );
         }

         return ( "" );
      }

      StringBuffer buf = new StringBuffer(  );

      if ( ( prefix != null ) && !prefix.equals( "" ) )
      {
         buf.append( prefix );
         buf.append( ":" );
      }

      buf.append( local_name );

      return ( buf.toString(  ) );
   }

   /**
    * DOCUMENT_ME
    *
    * @param buf       DOCUMENT_ME
    * @param soap_elem DOCUMENT_ME
    * @param depth     DOCUMENT_ME
    */
   private void appendAttributes( StringBuffer buf,
                                  SOAPElement  soap_elem,
                                  int          depth )
   {
      appendXmlnsAttributeIfNoPrefix( buf, soap_elem, depth );

      Iterator iter = soap_elem.getAllAttributes(  );

      while ( iter.hasNext(  ) )
      {
         Name attrib_pqname = (Name) iter.next(  );

         // skip all xmlns:foo attributes (e.g. xmlns:xs="urn:schema")
         if ( ( attrib_pqname.getPrefix(  ) != null )
              && attrib_pqname.getPrefix(  ).equals( XmlConstants.NSPREFIX_XMLNS ) )
         {
            continue;
         }

         // skip the xmlns attribute (e.g. xmlns="urn:default")
         if ( ( attrib_pqname.getLocalName(  ) != null )
              && attrib_pqname.getLocalName(  ).equals( XmlConstants.NSPREFIX_XMLNS ) )
         {
            continue;
         }

         appendAttribute( buf,
                          nameToString( attrib_pqname ),
                          soap_elem.getAttributeValue( attrib_pqname ),
                          depth );

         if ( ( ( attrib_pqname.getURI(  ) != null ) && !( "".equals( attrib_pqname.getURI(  ) ) ) )
              && ( ( attrib_pqname.getPrefix(  ) != null ) && !( "".equals( attrib_pqname.getPrefix(  ) ) ) )
              && ( soap_elem.getNamespaceURI( attrib_pqname.getPrefix(  ) ) == null ) )
         {
            appendNamespaceDeclarationAttribute( buf, attrib_pqname, depth );
         }
      }
   }

   /**
    * DOCUMENT_ME
    *
    * @param buf       DOCUMENT_ME
    * @param elem_name DOCUMENT_ME
    * @param depth     DOCUMENT_ME
    */
   private void appendElementOpener( StringBuffer buf,
                                     String       elem_name,
                                     int          depth )
   {
      appendIndentSpaces( buf, depth );
      buf.append( "<" );
      buf.append( elem_name );
   }

   /**
    * DOCUMENT_ME
    *
    * @param buf DOCUMENT_ME
    */
   private static void appendEmptyElementCloser( StringBuffer buf )
   {
      buf.append( " />\n" );
   }

   /**
    * DOCUMENT_ME
    *
    * @param buf       DOCUMENT_ME
    * @param elem_name DOCUMENT_ME
    * @param depth     DOCUMENT_ME
    */
   private void appendClosingElement( StringBuffer buf,
                                      String       elem_name,
                                      int          depth )
   {
      appendIndentSpaces( buf, depth );
      buf.append( "</" );
      buf.append( elem_name );
      buf.append( ">\n" );
   }

   /**
    * DOCUMENT_ME
    *
    * @param buf DOCUMENT_ME
    */
   private static void appendElementCloser( StringBuffer buf )
   {
      buf.append( ">\n" );
   }

   /**
    * @param buf
    * @param attrib_name
    * @param attrib_value
    */
   private void appendAttribute( StringBuffer buf,
                                 String       attrib_name,
                                 String       attrib_value,
                                 int          depth )
   {
      buf.append( "\n" );
      appendIndentSpaces( buf, depth );
      buf.append( attrib_name );
      buf.append( "=\"" );
      buf.append( attrib_value );
      buf.append( "\"" );
   }

   /**
    * DOCUMENT_ME
    *
    * @param buf      DOCUMENT_ME
    * @param children DOCUMENT_ME
    * @param depth    DOCUMENT_ME
    */
   private void appendChildren( StringBuffer buf,
                                Iterator     children,
                                SOAPElement  root_soap_elem,
                                int          depth )
   throws SOAPException
   {
      while ( children.hasNext(  ) )
      {
         Node child = (Node) children.next(  );

         buildSOAPNodeStringBuffer( buf, root_soap_elem, child, depth );
      }
   }

   /**
    * @param buf
    * @param depth
    */
   private void appendIndentSpaces( StringBuffer buf,
                                    int          depth )
   {
      if ( m_indent_str != null )
      {
         buf.append( org.apache.commons.lang.StringUtils.repeat( m_indent_str, depth ) );
      }
   }

   /**
    * Append an namespace declaration attribute of the form xmlns:prefix=nsuri.
    *
    * @param buf       the {@link StringBuffer} to be appended to
    * @param ns_pqname a {@link Name} containing the namespace URI and prefix to be appended; note that the localname
    *                  portion of ns_pqname is ignored
    * @param depth     the current indentation depth
    */
   private void appendNamespaceDeclarationAttribute( StringBuffer buf,
                                                     Name         ns_pqname,
                                                     int          depth )
   {
      if ( ns_pqname.getPrefix(  ).equals( XmlConstants.NSPREFIX_XMLNS ) )
      {
         //LOG.debug( "The prefix \"xmlns\" cannot be bound to any namespace explicitly. Skipping..." );
         return;
      }

      if ( ns_pqname.getURI(  ).equals( XmlConstants.NSURI_XMLNS ) )
      {
         //LOG.debug( "The namespace for \"xmlns\" cannot be bound to any prefix explicitly. Skipping..." );
         return;
      }

      String xmlns_prefix = XmlConstants.NSPREFIX_XMLNS;

      // if prefix was not the "default" prefix (xmlns:BLAH="xxx" vs. xmlns="xxx")
      if ( hasNonEmptyValue( ns_pqname.getPrefix(  ) ) )
      {
         xmlns_prefix += ( ":" + ns_pqname.getPrefix(  ) );
      }

      appendAttribute( buf,
                       xmlns_prefix,
                       ns_pqname.getURI(  ),
                       depth );
   }

   /**
    * DOCUMENT_ME
    *
    * @param buf   DOCUMENT_ME
    * @param elem  DOCUMENT_ME
    * @param depth DOCUMENT_ME
    */
   private void appendTextNode( StringBuffer buf,
                                Node         elem,
                                int          depth )
   throws SOAPException
   {
      Text text = (Text) elem;

      appendIndentSpaces( buf, depth );
      buf.append( getValue( text ) );
      buf.append( "\n" );
   }

   /**
    * @param buf
    * @param soap_elem
    * @param depth
    */
   private void appendXmlnsAttributeIfNoPrefix( StringBuffer buf,
                                                SOAPElement  soap_elem,
                                                int          depth )
   {
      Name elem_pqname = soap_elem.getElementName(  );

      if ( ( elem_pqname.getPrefix(  ) == null ) && ( elem_pqname.getURI(  ) != null ) )
      {
         appendAttribute( buf,
                          XmlConstants.NSPREFIX_XMLNS,
                          elem_pqname.getURI(  ),
                          depth );
      }
   }

   /**
    * @param buf       string buffer to append to
    * @param soap_elem a SOAP element; may not be null
    * @param depth     current recursion depth
    */
   private void appendXmlnsAttributes( StringBuffer buf,
                                       SOAPElement  soap_elem,
                                       int          depth )
   {
      Iterator prefixes             = soap_elem.getNamespacePrefixes(  );
      Set      encountered_prefixes = new HashSet(  );

      Name     name = soap_elem.getElementName(  );

      if ( hasNonEmptyValue( name.getPrefix(  ) ) && hasNonEmptyValue( name.getURI(  ) ) )
      {
         encountered_prefixes.add( name.getPrefix(  ) );
         appendNamespaceDeclarationAttribute( buf, name, depth );
      }

      while ( prefixes.hasNext(  ) )
      {
         String prefix = (String) prefixes.next(  );

         if ( encountered_prefixes.contains( prefix ) )
         {
            // duplicate prefix - skip it...
            continue;
         }

         encountered_prefixes.add( prefix );

         try
         {
            Name ns_pqname =
               SOAPFactory.newInstance(  ).createName( "",
                                                       prefix,
                                                       soap_elem.getNamespaceURI( prefix ) );

            appendNamespaceDeclarationAttribute( buf, ns_pqname, depth );
         }
         catch ( SOAPException soape )
         {
            //LOG.error( ResourceKeys.MSG.getMsg( ResourceKeys.METHOD_FAILED, "SOAPFactory.createName()" ),soape );
         }
      }
   }

   /**
    * Workhorse method for {@link #toString(javax.xml.soap.Node)} - calls itself recursively.
    *
    * @param buf               StringBuffer used to build up the string representation
    * @param current_soap_node a SAAJ SOAP node
    * @param depth             the current tree depth (used for indenting)
    */
   private StringBuffer buildSOAPNodeStringBuffer( StringBuffer buf,
                                                   Node         root_soap_node,
                                                   Node         current_soap_node,
                                                   int          depth )
   throws SOAPException
   {
      if ( isElement( current_soap_node ) )
      {
         SOAPElement soap_elem   = (SOAPElement) current_soap_node;
         Name        elem_pqname = null;

         try
         {
            elem_pqname = soap_elem.getElementName(  );
         }
         catch ( RuntimeException re )
         {
            //LOG.error( ResourceKeys.MSG.getMsg( ResourceKeys.METHOD_FAILED, "SOAPElement.getElementName()" ) );
         }

         String elem_name = nameToString( elem_pqname );

         if ( ( elem_pqname.getPrefix(  ) == null ) || elem_pqname.getPrefix(  ).equals( "" ) )
         {
            String prefix = getPrefix( elem_pqname, (SOAPElement) root_soap_node );

            if ( prefix != null )
            {
               elem_name = prefix + ":" + elem_name;
            }
         }

         appendElementOpener( buf, elem_name, depth );
         appendXmlnsAttributes( buf, soap_elem, depth + 1 );
         appendAttributes( buf, soap_elem, depth + 1 );

         Iterator children = getChildren( soap_elem );

         if ( children != null )
         {
            appendElementCloser( buf );
            appendChildren( buf, children, (SOAPElement) root_soap_node, depth + 1 );
            appendClosingElement( buf, elem_name, depth );
         }
         else
         {
            if ( hasNonEmptyValue( soap_elem ) )
            {
               appendElementCloser( buf );
               appendTextNode( buf, soap_elem, depth + 1 );
               appendClosingElement( buf, elem_name, depth );
            }
            else
            {
               appendEmptyElementCloser( buf );
            }
         }
      }
      else
      {
         appendTextNode( buf, current_soap_node, depth );
      }

      return ( buf );
   }

   /**
    * DOCUMENT_ME
    *
    * @param soap_elem DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    */
   private static boolean hasNonEmptyValue( SOAPElement soap_elem )
   {
      return ( soap_elem.getValue(  ) != null ) && !soap_elem.getValue(  ).trim(  ).equals( "" );
   }

   /**
    * @param pqname
    * @param current_soap_elem
    *
    * @return
    */
   private static String recursiveGetPrefix( Name        pqname,
                                             SOAPElement current_soap_elem )
   {
      String prefix = getPrefix( current_soap_elem,
                                 pqname.getURI(  ) );

      if ( ( prefix != null ) && !prefix.equals( "" ) )
      {
         return ( prefix );
      }

      Iterator children = current_soap_elem.getChildElements(  );

      while ( children.hasNext(  ) )
      {
         Object obj_child = children.next(  );

         if ( !( obj_child instanceof SOAPElement ) )
         {
            continue;
         }

         SOAPElement child = (SOAPElement) obj_child;

         prefix = getPrefix( child,
                             pqname.getURI(  ) );

         if ( ( prefix != null ) && !prefix.equals( "" ) )
         {
            break;
         }

         prefix = recursiveGetPrefix( pqname, child );

         if ( ( prefix != null ) && !prefix.equals( "" ) )
         {
            break;
         }
      }

      return ( prefix );
   }
}
TOP

Related Classes of org.apache.ws.util.helper.Saaj2StringConverter

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.