Package org.apache.axis2.jaxws.context.listener

Source Code of org.apache.axis2.jaxws.context.listener.ParserInputStreamCustomBuilder

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.axis2.jaxws.context.listener;

import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;

import javax.xml.soap.SOAPConstants;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;

import org.apache.axiom.om.OMContainer;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMSourcedElement;
import org.apache.axiom.om.ds.ParserInputStreamDataSource;
import org.apache.axiom.om.impl.builder.CustomBuilder;
import org.apache.axis2.datasource.jaxb.JAXBCustomBuilderMonitor;
import org.apache.axis2.jaxws.handler.HandlerUtils;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.jaxws.message.databinding.ParsedEntityReader;
import org.apache.axis2.jaxws.message.factory.ParsedEntityReaderFactory;
import org.apache.axis2.jaxws.registry.FactoryRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A custom builder to that does the following:
* 1) Uses the parser to fetch the inputStream if parser supports reading of element contents
* 2) Use the inputStream to create a DataSource backed by the InputStream read from Parser.
* 3) Use the OMFactory to create OMSourcedElement, OMSourcedElement is backed by ParsedEntityDataSource.
*/

public class ParserInputStreamCustomBuilder implements CustomBuilder {
    private static final Log log =
        LogFactory.getLog(ParserInputStreamCustomBuilder.class);

    private String encoding = null;

    /**
     * Constructor
     * @param encoding
     */
    public ParserInputStreamCustomBuilder(String encoding) {
        this.encoding = (encoding == null) ? "utf-8" :encoding;
    }
    /*
     * (non-Javadoc)
     * @see org.apache.axiom.om.impl.builder.CustomBuilder#create(java.lang.String, java.lang.String, org.apache.axiom.om.OMContainer, javax.xml.stream.XMLStreamReader, org.apache.axiom.om.OMFactory)
     */
    public OMElement create(String namespace,
        String localPart,
        OMContainer parent,
        XMLStreamReader reader,
        OMFactory factory) throws OMException {

        if (log.isDebugEnabled()) {
            log.debug("create namespace = " + namespace);
            log.debug("  localPart = " + localPart);
            log.debug("  reader = " + reader.getClass());
        }
       
        if (!shouldUnmarshal(namespace, localPart)) {
            if (log.isDebugEnabled()) {
                log.debug("This element won't be unmarshalled with the custom builder");
            }
            return null;
        }
       
        /*
         * 1) Use the the parser to fetch the inputStream
         * 2) Use the inputStream to create a DataSource, delay reading of content as much as you can.
         * 3) Use the OMFactory to create OMSourcedElement, OMSourcedElement is backed by ParsedEntityDataSource.
         */
        try{
            ParsedEntityReaderFactory perf = (ParsedEntityReaderFactory)FactoryRegistry.getFactory(ParsedEntityReaderFactory.class);
            ParsedEntityReader entityReader = perf.getParsedEntityReader();
            if (log.isDebugEnabled()) {
                log.debug("ParsedEntityReader = " + entityReader);
            }
            //Do not user custom builder if Parser does not have ability to read sub content.
            if(!entityReader.isParsedEntityStreamAvailable()){
                if (log.isDebugEnabled()) {
                    log.debug("ParsedEntityStream is not available, defaulting to normal build");
                }
                return null;
            }
            // Create an OMSourcedElement backed by the ParsedData
            InputStream parsedStream = getPayloadContent(reader, entityReader);
            if(parsedStream == null){
                //cant read content from EntityReader, returning null.
                if (log.isDebugEnabled()) {
                    log.debug("Unable to read content from the entity reader, defaulting to normal build");
                }
                return null;
            }
            HashMap<String, String> nsElementDecls = getElementNamespaceDeclarations(reader);
            HashMap<String, String> attrElementDecls = getElementAttributeDeclarations(reader);
           
            //read the payload. Lets move the parser forward.
            if(reader.hasNext()){
                reader.next();
            }
            if(namespace == null){
                //lets look for ns in reader
                namespace = reader.getNamespaceURI();
                if(namespace == null){
                    //still cant find the namespace, just set it to "";
                    namespace = "";
                }
            }
            OMNamespace ns = factory.createOMNamespace(namespace, reader.getPrefix());
            InputStream payload = ContextListenerUtils.createPayloadElement(parsedStream, ns, localPart, parent,
                        nsElementDecls, attrElementDecls);

            ParserInputStreamDataSource ds = new ParserInputStreamDataSource(payload, encoding);
            OMSourcedElement om = null;
            if (parent instanceof SOAPHeader && factory instanceof SOAPFactory) {
                om = ((SOAPFactory)factory).createSOAPHeaderBlock(localPart, ns, ds);
            } else {
                om = factory.createOMElement(ds, localPart, ns);
            }          
            //Add the new OMSourcedElement ot the parent
            parent.addChild(om);
            /*
            //Lets Mark the body as complete so Serialize calls dont fetch data from parser for body content.
            if(parent instanceof SOAPBodyImpl){
                ((SOAPBodyImpl)parent).setComplete(true);
            }
            */
            return om;
        } catch (OMException e) {
            throw e;
        } catch (Throwable t) {
            throw new OMException(t);
        }
    }

    public OMElement create(String namespace,
        String localPart,
        OMContainer parent,
        XMLStreamReader reader,
        OMFactory factory,
        InputStream payload) throws OMException {

        if (log.isDebugEnabled()) {
            log.debug("create namespace = " + namespace);
            log.debug("  localPart = " + localPart);
            log.debug("  reader = " + reader.getClass());
        }
        /*
         * 1) Use the the parser to fetch the inputStream
         * 2) Use the inputStream to create a DataSource, delay reading of content as much as you can.
         * 3) Use the OMFactory to create OMSourcedElement, OMSourcedElement is backed by ParsedEntityDataSource.
         */
        try{
            if(namespace == null){
                //lets look for ns in reader
                namespace = reader.getNamespaceURI();
                if(namespace == null){
                    //still cant find the namespace, just set it to "";
                    namespace = "";
                }
            }
            if (!shouldUnmarshal(namespace, localPart)) {
                if (log.isDebugEnabled()) {
                    log.debug("This element won't be unmarshalled with the custom builder");
                }
                return null;
            }
            OMNamespace ns = factory.createOMNamespace(namespace, reader.getPrefix());
            ParserInputStreamDataSource ds = new ParserInputStreamDataSource(payload, encoding);
            OMSourcedElement om = null;
            if (parent instanceof SOAPHeader && factory instanceof SOAPFactory) {
                om = ((SOAPFactory)factory).createSOAPHeaderBlock(localPart, ns, ds);
            } else {
                om = factory.createOMElement(ds, localPart, ns);
            }          
            //Add the new OMSourcedElement ot the parent
            parent.addChild(om);
            return om;
        } catch (OMException e) {
            throw e;
        } catch (Throwable t) {
            throw new OMException(t);
        }
    }

    private HashMap<String, String> getElementNamespaceDeclarations(XMLStreamReader reader)
    {
      HashMap<String, String> nsElementDecls = new HashMap<String, String>();
      int count = reader.getNamespaceCount();
      for (int i = 0; i < count; i++){
        String prefix = reader.getNamespacePrefix(i);
        String namespace = reader.getNamespaceURI(i);
        if (namespace != null && namespace.length() > 0){
          nsElementDecls.put(prefix == null ? "":prefix, namespace);
        }
      }
      return nsElementDecls;
    }
   
    private HashMap<String, String> getElementAttributeDeclarations(XMLStreamReader reader)
    {
      HashMap<String, String> attrElementDecls = new HashMap<String, String>();
      int count = reader.getAttributeCount();

      for (int i = 0; i < count; i++) {
        String prefix = reader.getAttributePrefix(i);
        String name = reader.getAttributeLocalName(i);
        String value = convertEntityReferences(reader.getAttributeValue(i));
        String compoundName;
        if (prefix != null && prefix.length() > 0){
          compoundName = prefix+":"+name;
        }
        else {
          compoundName = name;
        }
        attrElementDecls.put(compoundName, value);
      }
      return attrElementDecls;
    }
   
    protected String convertEntityReferences(String value)
    {
      if ((value == null) || (value.length() == 0))
        return value;
     
      int valueLen = value.length();
     
      int[] positionsToChange = null;
      int numChanged = 0;
     
      for (int i = 0; i < valueLen; i++) {
        switch (value.charAt(i)) {
          case '<':
          case '>':
          case '&':
          case '\"':
          case '\'':
            if (positionsToChange == null)
            {
              positionsToChange = new int[valueLen];
            }
            positionsToChange[numChanged++]=i;
            break;
        }
      }

      if (numChanged == 0) {
        if(log.isDebugEnabled())
        {
          log.debug("No entity references were found in "+value);
        }
        return value;
      }
      else {
        if(log.isDebugEnabled())
        {
          log.debug("Found "+numChanged+" entity references in "+value);
        }
       
        //We'll create the new builder assuming the size of the worst case
        StringBuilder changedValue = new StringBuilder(valueLen+numChanged*5);
        int changedPos = 0;
        for (int i = 0; i < valueLen; i++) {
          if (i == positionsToChange[changedPos]) {
            switch (value.charAt(i)) {
              case '<':
                changedValue.append("&lt;");
                changedPos++;
                break;
              case '>':
                changedValue.append("&gt;");
                changedPos++;
                break;
              case '&':
                changedValue.append("&amp;");
                changedPos++;
                break;
              case '\'':
                changedValue.append("&apos;");
                changedPos++;
                break;
              case '\"':
                changedValue.append("&quot;");
                changedPos++;
                break;
            }
          }
          else {
            changedValue.append(value.charAt(i));
          }
        }

        if(log.isDebugEnabled())
        {
          log.debug("Converted to "+changedValue.toString());
        }

        return changedValue.toString();
      }
    }
    /*
     * Read content from entityReader.
     */
    private InputStream getPayloadContent(XMLStreamReader parser, ParsedEntityReader entityReader){
        int event = parser.getEventType();
        //Make sure its start element event.
        if(log.isDebugEnabled()){
            log.debug("checking if event is START_ELEMENT");
        }
        InputStream parsedStream = null;
        if(event == XMLStreamConstants.START_ELEMENT){
            if(log.isDebugEnabled()){
                log.debug("event is START_ELEMENT");
            }
            parsedStream = entityReader.readParsedEntityStream(parser);
            if(parsedStream!=null){
                if(log.isDebugEnabled()){
                    log.debug("Read Parsed EntityStream");
                }
            }
        }
        return parsedStream;
    }
   
    /**
     * @param namespace
     * @param localPart
     * @return true if this ns and local part is acceptable for unmarshalling
     */
    private boolean shouldUnmarshal(String namespace, String localPart) {
       
        /**
         * The stream preserves the original message, so I think
         * we want to do unmarshal even if high fidelity is specified.
        
        boolean isHighFidelity = HandlerUtils.isHighFidelity(msgContext);

        if (isHighFidelity) {
            return false;
        }
        */
       
        // Don't unmarshal SOAPFaults.
        // If there is no localPart, this also indicates a potential problem...so don't
        // use the custom builder
        if (localPart == null ||
            (localPart.equals("Fault") &&
             (SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(namespace) ||
              SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE.equals(namespace)))) {
            return false;
        }
      
       
        /**
         * For JAXB custom building, we ignore security elements.
         * I don't think it matters for parsed entities since they preserve all the content
        if (localPart.equals("EncryptedData")) {
            return false;
        }
        */
       
        return true;
               
    }
}
TOP

Related Classes of org.apache.axis2.jaxws.context.listener.ParserInputStreamCustomBuilder

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.