/**
   * Marshal inputObjects to SOAP xml. If the exchange or message has an EXCEPTION_CAUGTH property
   * or header then instead of the object the exception is marshaled.
   *
   * <p>To determine the name of the top level xml elements the elementNameStrategy is used.
   *
   * @throws IOException,SAXException
   */
  public void marshal(Exchange exchange, Object inputObject, OutputStream stream)
      throws IOException, SAXException {
    checkElementNameStrategy(exchange);

    String soapAction = getSoapActionFromExchange(exchange);
    if (soapAction == null && inputObject instanceof BeanInvocation) {
      BeanInvocation beanInvocation = (BeanInvocation) inputObject;
      WebMethod webMethod = beanInvocation.getMethod().getAnnotation(WebMethod.class);
      if (webMethod != null && webMethod.action() != null) {
        soapAction = webMethod.action();
      }
    }

    Object envelope = adapter.doMarshal(exchange, inputObject, stream, soapAction);

    // and continue in super
    super.marshal(exchange, envelope, stream);
  }
  /**
   * Create body content from a non Exception object. If the inputObject is a BeanInvocation the
   * following should be considered: The first parameter will be used for the SOAP body.
   * BeanInvocations with more than one parameter are not supported. So the interface should be in
   * doc lit bare style.
   *
   * @param inputObject object to be put into the SOAP body
   * @param soapAction for name resolution
   * @param headerElements in/out parameter used to capture header content if present
   * @return JAXBElement for the body content
   */
  protected List<JAXBElement<?>> createContentFromObject(
      final Object inputObject, String soapAction, List<JAXBElement<?>> headerElements) {
    List<Object> bodyParts = new ArrayList<Object>();
    List<Object> headerParts = new ArrayList<Object>();
    if (inputObject instanceof BeanInvocation) {
      BeanInvocation bi = (BeanInvocation) inputObject;
      Annotation[][] annotations = bi.getMethod().getParameterAnnotations();

      List<WebParam> webParams = new ArrayList<WebParam>();
      for (Annotation[] singleParameterAnnotations : annotations) {
        for (Annotation annotation : singleParameterAnnotations) {
          if (annotation instanceof WebParam) {
            webParams.add((WebParam) annotation);
          }
        }
      }

      if (webParams.size() > 0) {
        if (webParams.size() == bi.getArgs().length) {
          int index = -1;
          for (Object o : bi.getArgs()) {
            if (webParams.get(++index).header()) {
              headerParts.add(o);
            } else {
              bodyParts.add(o);
            }
          }
        } else {
          throw new RuntimeCamelException(
              "The number of bean invocation parameters does not "
                  + "match the number of parameters annotated with @WebParam for the method [ "
                  + bi.getMethod().getName()
                  + "].");
        }
      } else {
        // try to map all objects for the body
        for (Object o : bi.getArgs()) {
          bodyParts.add(o);
        }
      }

    } else {
      bodyParts.add(inputObject);
    }

    List<JAXBElement<?>> bodyElements = new ArrayList<JAXBElement<?>>();
    for (Object bodyObj : bodyParts) {
      QName name = elementNameStrategy.findQNameForSoapActionOrType(soapAction, bodyObj.getClass());
      if (name == null) {
        LOG.warn("Could not find QName for class " + bodyObj.getClass().getName());
        continue;
      } else {
        bodyElements.add(getElement(bodyObj, name));
      }
    }

    for (Object headerObj : headerParts) {
      QName name =
          elementNameStrategy.findQNameForSoapActionOrType(soapAction, headerObj.getClass());
      if (name == null) {
        LOG.warn("Could not find QName for class " + headerObj.getClass().getName());
        continue;
      } else {
        JAXBElement<?> headerElem = getElement(headerObj, name);
        if (null != headerElem) {
          headerElements.add(headerElem);
        }
      }
    }

    return bodyElements;
  }