Package de.danet.an.workflow.tools.soapclient

Source Code of de.danet.an.workflow.tools.soapclient.SAXEventBufferAxisSerializer

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* $Id: SAXEventBufferAxisSerializer.java 2326 2007-03-27 21:59:44Z mlipp $
*
* $Log$
* Revision 1.2  2006/09/29 12:32:13  drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.1.1.2  2004/08/18 15:17:39  drmlipp
* Update to 1.2
*
* Revision 1.3  2004/03/17 12:43:02  lipp
* Added arrayType generation for arrays.
*
* Revision 1.2  2003/06/27 08:51:44  lipp
* Fixed copyright/license information.
*
* Revision 1.1  2003/06/24 16:08:12  lipp
* Implemented invocation.
*
*/
package de.danet.an.workflow.tools.soapclient;

import java.io.IOException;
import java.io.Serializable;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.xml.namespace.QName;

import org.w3c.dom.Element;

import org.apache.axis.Constants;
import org.apache.axis.MessageContext;
import org.apache.axis.encoding.SerializationContext;
import org.apache.axis.encoding.Serializer;
import org.apache.axis.schema.SchemaVersion;
import org.apache.axis.soap.SOAPConstants;
import org.apache.axis.utils.Messages;
import org.apache.axis.wsdl.fromJava.Types;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import de.danet.an.util.XMLUtil;
import de.danet.an.util.sax.HandlerStack;
import de.danet.an.util.sax.StackedHandler;

import de.danet.an.workflow.api.SAXEventBuffer;

/**
* General purpose serializer/deserializerFactory for SAXEventBuffer in
* the AXIS mplementation of the JAX-RPC interface.
* Creates a xml output for a given SAXEventBuffer,
* preserving the stucture and text content.
*/
public class SAXEventBufferAxisSerializer implements Serializer, Serializable {

    private static final org.apache.commons.logging.Log logger
  = org.apache.commons.logging.LogFactory.getLog
  (SAXEventBufferAxisSerializer.class);

    /**
     * Helper class that holds a namespace uri and a local name.
     */
    private class NsAndLocal {
  private String namespace;
  private String localName;

  /**
   * Create a new object with attributes initialized to the
   * given values.
   * @param n the namespace
   * @param l the local name
   */
  public NsAndLocal (String n, String l) {
      namespace = n;
      localName = l;
  }

  /**
   * Return the namespace.
   * @return namespace
   */
  public String namespace () {
      return namespace;
  }

  /**
   * Return the local name.
   * @return local name
   */
  public String localName () {
      return localName;
  }

  /**
   * Compare with other object.
   * @param o other object
   * @return <code>true</code> if equal
   */
  public boolean equals (Object o) {
      String ons = ((NsAndLocal)o).namespace;
      if (namespace == null && ons != null
    || namespace != null && ons == null
    || namespace != null && ons != null && !namespace.equals(ons)) {
    return false;
      }
      return localName.equals (((NsAndLocal)o).localName);
  }

  /**
   * Return a hash code.
   * @return the hash code
   */
  public int hashCode () {
      return namespace.hashCode() ^ localName.hashCode();
  }

  /**
   * Return a string representation for debugging purposes.
   * @return string representation
   */
  public String toString () {
      return "{" + namespace + "}" + localName;
  }
    }
   
    /**
     * Default constructor.
     */
    public SAXEventBufferAxisSerializer() {
    }
   
    /**
     * From the Serializer interface.
     * @param name name
     * @param attributes attributes
     * @param value value
     * @param context context
     * @throws IOException IOException
     */
    public void serialize(QName name, Attributes attributes,
        Object value, SerializationContext context)
  throws IOException {
  logger.debug("SAXEventBufferAxis serialize() called for \"" + name + "\"");
  if (!(value instanceof SAXEventBuffer)) {
            throw new IOException(Messages.getMessage("can not serialize!"));
  }

        MessageContext msgContext = context.getMessageContext();
        SchemaVersion schema = SchemaVersion.SCHEMA_2001;
        SOAPConstants soap = SOAPConstants.SOAP11_CONSTANTS;
        if(msgContext != null) {
            schema = msgContext.getSchemaVersion();
            soap = msgContext.getSOAPConstants();
        }

  try {
      int typeIdx = attributes.getIndex (schema.getXsiURI(), "type");
      if (typeIdx >= 0) {
    String prefixForSoapEnc
        = context.getPrefixForURI(soap.getEncodingURI());
    if (logger.isDebugEnabled ()) {
        logger.debug
      ("Type is \"" + attributes.getValue(typeIdx) + "\""
       + " (\""+prefixForSoapEnc+":Array\" denotes array)");
    }
    if (attributes.getValue(typeIdx)
        .equals(prefixForSoapEnc + ":Array")
        && attributes.getIndex(soap.getEncodingURI(),
             soap.getAttrItemType()) == -1) {
        AttributesImpl attrs = new AttributesImpl (attributes);
        attrs.addAttribute
      (soap.getEncodingURI(), soap.getAttrItemType(),
       prefixForSoapEnc + ":arrayType", "CDATA",
       determineArrayType ((SAXEventBuffer)value, context));
        attributes = attrs;
    }
      }
     
      context.startElement(name, attributes);
      ((SAXEventBuffer)value).emit (new EventForwarder (context));
      context.endElement();
      logger.debug("SAXEventBuffer serialize() called");
  } catch (SAXException e) {
      logger.error ("Problem creating XML argument: "
        + e.getMessage (), e);
      throw new IOException (e.getMessage ());
  }
    }

    private class ArrayTypeExtractor extends StackedHandler {

  private SchemaVersion schema = SchemaVersion.SCHEMA_2001;
  private int items = 0;
  private boolean typeValid = true;

  /**
   * Create a new event forwarder.
   * @param context the context to forward to
   */
  public ArrayTypeExtractor (SerializationContext context) {
      MessageContext msgContext = context.getMessageContext();
      if(msgContext != null) {
    schema = msgContext.getSchemaVersion();
      }
  }

  /**
   * Receive notification of the beginning of an element.
   *
   * @param namespaceURI The Namespace URI, or the empty string if the
   *        element has no Namespace URI or if Namespace
   *        processing is not being performed.
   * @param localName The local name (without prefix), or the
   *        empty string if Namespace processing is not being
   *        performed.
   * @param qName The qualified name (with prefix), or the
   *        empty string if qualified names are not available.
   * @param atts The attributes attached to the element.  If
   *        there are no attributes, it shall be an empty
   *        Attributes object.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see #endElement
   * @see org.xml.sax.Attributes
   */
  public void startElement (String namespaceURI, String localName,
          String qName, Attributes atts)
      throws SAXException {
      if (getStack().getRelativeDepth() != 1) {
    return;
      }
      // top level element, i.e. item
      items += 1;
      setContextData ("items", new Integer (items));
      if (!typeValid) {
    return;
      }
      int typeIdx = atts.getIndex (schema.getXsiURI(), "type");
      if (typeIdx < 0) {
    logger.warn ("Type declaration missing in array element "
           + items);
    typeValid = false;
    setContextData ("typesValid", Boolean.FALSE);
    return;
      }
      String typeQName = atts.getValue(typeIdx);
      NsAndLocal type = null;
      int colonPos = typeQName.indexOf(':');
      if (colonPos < 0) {
    type = new NsAndLocal (null, typeQName);
      } else {
    String typeURI = getStack().getURIForPrefix
        (typeQName.substring(0, colonPos));
    if (typeURI == null) {
        logger.warn ("Invalid type declaration in array element "
         + items + ": uses undefined prefix in qname");
        typeValid = false;
        setContextData ("typesValid", Boolean.FALSE);
        return;
    }
    type = new NsAndLocal
        (typeURI, typeQName.substring(colonPos + 1));
      }
      if (logger.isDebugEnabled ()) {
    logger.debug ("Type of element " + items + " is " + type);
      }
      ((Set)getContextData("types")).add (type);
  }
    }

    private String determineArrayType
  (SAXEventBuffer buf, SerializationContext context)
  throws SAXException {
  HandlerStack hs = new HandlerStack (new ArrayTypeExtractor(context));
  hs.setContextData("types", new HashSet ());
  hs.setContextData ("items", new Integer (0));
  hs.setContextData ("typesValid", Boolean.TRUE);
  hs.contentHandler().startElement
      ("", "root", "root", new AttributesImpl ());
  buf.emit (hs.contentHandler());
  hs.contentHandler().endElement ("", "root", "root");
  Set types = (Set)hs.getContextData("types");
  String xsdPref = context.getPrefixForURI(XMLUtil.XMLNS_SCHEMA);
  String arrayType;
  String dim = "[" + (Integer)hs.getContextData("items") + "]";
  if (!((Boolean)hs.getContextData ("typesValid")).booleanValue()
      || types.size () > 1) {
      arrayType = xsdPref + ":" + "ur-type" + dim;
  } else {
      Iterator i = types.iterator();
      NsAndLocal type = (NsAndLocal)i.next ();
      String typePref = context.getPrefixForURI(type.namespace());
      arrayType = typePref + ":" + type.localName() + dim;
  }
  if (logger.isDebugEnabled ()) {
      logger.debug ("Array type is " + arrayType);
  }
  return arrayType;
    }

    private class EventForwarder implements ContentHandler {

  private SerializationContext ctx;

  /**
   * Receive an object for locating the origin of SAX document events.
   *
   * @param locator An object that can return the location of any
   * SAX document event.
   * @see org.xml.sax.Locator
   */
  public void setDocumentLocator (Locator locator) {
      // ignore
  }

  /**
   * Create a new event forwarder.
   * @param context the context to forward to
   */
  public EventForwarder (SerializationContext context) {
      ctx = context;
  }

  /**
   * Receive notification of the beginning of a document.
   *
   * @throws SAXException Any SAX exception, possibly
   * wrapping another exception.
   * @see #endDocument
   */
  public void startDocument() throws SAXException {
      // shouldn't be called
  }
 
  /**
   * Receive notification of the end of a document.
   *
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see #startDocument
   */
  public void endDocument() throws SAXException {
      // shouldn't be called
  }

  /**
   * Begin the scope of a prefix-URI Namespace mapping.
   *
   * @param prefix The Namespace prefix being declared.
   * @param uri The Namespace URI the prefix is mapped to.
   * @throws SAXException The client may throw an
   * exception during processing.
   * @see #endPrefixMapping
   * @see #startElement
   */
  public void startPrefixMapping (String prefix, String uri)
      throws SAXException {
      ctx.registerPrefixForURI(prefix, uri);
  }

  /**
   * End the scope of a prefix-URI mapping.
   *
   * @param prefix The prefix that was being mapping.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see #startPrefixMapping
   * @see #endElement
   */
  public void endPrefixMapping(String prefix) throws SAXException {
      // nothing to do
  }

  /**
   * Receive notification of the beginning of an element.
   *
   * @param namespaceURI The Namespace URI, or the empty string if the
   *        element has no Namespace URI or if Namespace
   *        processing is not being performed.
   * @param localName The local name (without prefix), or the
   *        empty string if Namespace processing is not being
   *        performed.
   * @param qName The qualified name (with prefix), or the
   *        empty string if qualified names are not available.
   * @param atts The attributes attached to the element.  If
   *        there are no attributes, it shall be an empty
   *        Attributes object.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see #endElement
   * @see org.xml.sax.Attributes
   */
  public void startElement (String namespaceURI, String localName,
          String qName, Attributes atts)
      throws SAXException {
      try {
    AttributesImpl a = new AttributesImpl ();
    // Axis has some problems with namespaces reported
    // as attributes, filter them out
    for (int i = 0; i < atts.getLength(); i++) {
        if (! atts.getURI(i).equals (XMLUtil.XMLNS_NS)) {
      a.addAttribute (atts.getURI(i), atts.getLocalName(i),
          atts.getQName(i), atts.getType(i),
          atts.getValue(i));
        }
    }
    ctx.startElement(new QName (namespaceURI, localName), a);
      } catch (IOException e) {
    throw new SAXException (e);
      }
  }

  /**
   * Receive notification of the end of an element.
   *
   * @param namespaceURI The Namespace URI, or the empty string if the
   *        element has no Namespace URI or if Namespace
   *        processing is not being performed.
   * @param localName The local name (without prefix), or the
   *        empty string if Namespace processing is not being
   *        performed.
   * @param qName The qualified XML 1.0 name (with prefix), or the
   *        empty string if qualified names are not available.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   */
  public void endElement (String namespaceURI, String localName,
        String qName)
      throws SAXException {
      try {
    ctx.endElement();
      } catch (IOException e) {
    throw new SAXException (e);
      }
  }

  /**
   * Receive notification of character data.
   *
   * @param ch The characters from the XML document.
   * @param start The start position in the array.
   * @param length The number of characters to read from the array.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see #ignorableWhitespace
   * @see org.xml.sax.Locator
   */
  public void characters (char[] ch, int start, int length)
      throws SAXException {
      try {
    ctx.writeChars(ch, start, length);
      } catch (IOException e) {
    throw new SAXException (e);
      }
  }
 
  /**
   * Receive notification of ignorable whitespace in element content.
   *
   * @param ch The characters from the XML document.
   * @param start The start position in the array.
   * @param length The number of characters to read from the array.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @see #characters
   */
  public void ignorableWhitespace (char[] ch, int start, int length)
      throws SAXException {
      try {
    ctx.writeChars(ch, start, length);
      } catch (IOException e) {
    throw new SAXException (e);
      }
  }

  /**
   * Receive notification of a processing instruction.
   *
   * @param target The processing instruction target.
   * @param data The processing instruction data, or null if
   *        none was supplied.  The data does not include any
   *        whitespace separating it from the target.
   * @throws SAXException Any SAX exception, possibly
   *            wrapping another exception.
   */
  public void processingInstruction (String target, String data)
      throws SAXException {
  }
 
  /**
   * Receive notification of a skipped entity.
   *
   * @param name The name of the skipped entity.  If it is a
   * parameter entity, the name will begin with '%', and if it is
   * the external DTD subset, it will be the string "[dtd]".
   * @throws SAXException Any SAX exception, possibly
   * wrapping another exception.
   */
  public void skippedEntity (String name)
      throws SAXException {
  }
    }

    /**
     * From the Serializer interface (Axis pre 1.1 version).
     * Currently we do not support serialization.
     * @param types types
     * @return false
     */
    public boolean writeSchema(Types types){
   return false;
    }
   
    /**
     * Return XML schema for the specified type, suitable for insertion into
     * the &lt;types&gt; element of a WSDL document, or underneath an
     * &lt;element&gt; or &lt;attribute&gt; declaration.
     *
     * @param javaType the Java Class we're writing out schema for
     * @param types the Java2WSDL Types object which holds the context
     *              for the WSDL being generated
     * @return a type element containing a schema simpleType/complexType
     * @throws Exception if an error occurs
     * @see org.apache.axis.wsdl.fromJava.Types
     */
    public Element writeSchema(Class javaType, Types types) throws Exception {
        return null;
    }

    /**
     * From the Serializer and Deserializerinterface.
     * @return Constants.AXIS_SAX
     */
    public String getMechanismType() {
  return Constants.AXIS_SAX;
    }

}
TOP

Related Classes of de.danet.an.workflow.tools.soapclient.SAXEventBufferAxisSerializer

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.