View Javadoc

    1   package org.codehaus.xfire.service.binding;
    2
    3   import java.util.ArrayList;
    4   import java.util.Collection;
    5   import java.util.Iterator;
    6   import java.util.List;
    7
    8   import javax.wsdl.Message;
    9   import javax.wsdl.Part;
    10  import javax.xml.namespace.QName;
    11  import javax.xml.stream.XMLStreamException;
    12  import javax.xml.stream.XMLStreamWriter;
    13
    14  import org.codehaus.xfire.MessageContext;
    15  import org.codehaus.xfire.XFireRuntimeException;
    16  import org.codehaus.xfire.exchange.InMessage;
    17  import org.codehaus.xfire.exchange.MessageSerializer;
    18  import org.codehaus.xfire.exchange.OutMessage;
    19  import org.codehaus.xfire.fault.XFireFault;
    20  import org.codehaus.xfire.service.MessageInfo;
    21  import org.codehaus.xfire.service.MessagePartInfo;
    22  import org.codehaus.xfire.service.OperationInfo;
    23  import org.codehaus.xfire.service.Service;
    24  import org.codehaus.xfire.soap.SoapConstants;
    25  import org.codehaus.xfire.util.DepthXMLStreamReader;
    26  import org.codehaus.xfire.util.STAXUtils;
    27  import org.codehaus.xfire.wsdl.SchemaType;
    28  import org.codehaus.xfire.wsdl11.WSDL11ParameterBinding;
    29  import org.codehaus.xfire.wsdl11.builder.AbstractWSDL;
    30  import org.codehaus.xfire.wsdl11.builder.WSDLBuilder;
    31  import org.codehaus.yom.Attribute;
    32  import org.codehaus.yom.Element;
    33
    34  public class WrappedBinding
    35      extends AbstractBinding
    36      implements WSDL11ParameterBinding, MessageSerializer
    37  {
    38      public WrappedBinding()
    39      {
    40          setStyle(SoapConstants.STYLE_WRAPPED);
    41          setUse(SoapConstants.USE_LITERAL);
    42      }
    43
    44      public void readMessage(InMessage inMessage, MessageContext context)
    45          throws XFireFault
    46      {
    47          Service endpoint = context.getService();
    48
    49          List parameters = new ArrayList();
    50          DepthXMLStreamReader dr = new DepthXMLStreamReader(context.getInMessage().getXMLStreamReader());
    51
    52          if ( !STAXUtils.toNextElement(dr) )
    53              throw new XFireFault("There must be a method name element.", XFireFault.SENDER);
    54
    55          MessageInfo msgInfo = null;
    56          if (isClientModeOn())
    57          {
    58              OperationInfo op = context.getExchange().getOperation();
    59
    60              msgInfo = op.getOutputMessage();
    61          }
    62          else
    63          {
    64              if (context.getExchange().getOperation() == null)
    65              {
    66                  OperationInfo op = endpoint.getServiceInfo().getOperation( dr.getLocalName() );
    67
    68                  if (op == null)
    69                  {
    70                      throw new XFireFault("Invalid operation: " + dr.getName(), XFireFault.SENDER);
    71                  }
    72
    73                  setOperation(op, context);
    74              }
    75
    76              msgInfo = context.getExchange().getOperation().getInputMessage();
    77          }
    78
    79          // Move from Operation element to whitespace or start element
    80          nextEvent(dr);
    81
    82          while(STAXUtils.toNextElement(dr))
    83          {
    84              MessagePartInfo p = msgInfo.getMessagePart(dr.getName());
    85
    86              if (p == null)
    87              {
    88                  throw new XFireFault("Parameter " + dr.getName() + " does not exist!",
    89                                       XFireFault.SENDER);
    90              }
    91
    92              parameters.add( getBindingProvider().readParameter(p, inMessage.getXMLStreamReader(), context) );
    93          }
    94
    95          inMessage.setBody(parameters);
    96      }
    97
    98      public void writeMessage(OutMessage message, XMLStreamWriter writer, MessageContext context)
    99          throws XFireFault
    100     {
    101         try
    102         {
    103             Service endpoint = context.getService();
    104             Object[] values = (Object[]) message.getBody();
    105
    106             OperationInfo op = context.getExchange().getOperation();
    107             String name = null;
    108
    109             MessageInfo msgInfo = null;
    110             if (isClientModeOn())
    111             {
    112                 name = op.getName();
    113                 msgInfo = op.getInputMessage();
    114             }
    115             else
    116             {
    117                 name = op.getName() + "Response";
    118                 msgInfo = op.getOutputMessage();
    119             }
    120
    121             writeStartElement(writer, name, endpoint.getServiceInfo().getName().getNamespaceURI());
    122
    123             int i = 0;
    124             for(Iterator itr = msgInfo.getMessageParts().iterator(); itr.hasNext();)
    125             {
    126                 MessagePartInfo outParam = (MessagePartInfo) itr.next();
    127
    128                 getBindingProvider().writeParameter(outParam, writer, context, values[i]);
    129                 i++;
    130             }
    131
    132             writer.writeEndElement();
    133         }
    134         catch (XMLStreamException e)
    135         {
    136             throw new XFireRuntimeException("Couldn't write start element.", e);
    137         }
    138     }
    139
    140     public void writeStartElement(XMLStreamWriter writer, String name, String namespace)
    141         throws XMLStreamException
    142     {
    143         String prefix = "";
    144
    145         writer.setPrefix(prefix, namespace);
    146         writer.writeStartElement(prefix, name, namespace);
    147         writer.writeNamespace(prefix, namespace);
    148     }
    149
    150     public void createInputParts(WSDLBuilder builder,
    151                                  Message req,
    152                                  OperationInfo op)
    153     {
    154         Part part = builder.getDefinition().createPart();
    155
    156         QName typeQName = createDocumentType(builder,
    157                                              op.getInputMessage(),
    158                                              part,
    159                                              op.getName());
    160         part.setName("parameters");
    161         part.setElementName(typeQName);
    162
    163         req.addPart(part);
    164     }
    165
    166     public void createOutputParts(WSDLBuilder builder,
    167                                   Message req,
    168                                   OperationInfo op)
    169     {
    170         // response message part
    171         Part part = builder.getDefinition().createPart();
    172
    173         // Document style service
    174         QName typeQName = createDocumentType(builder,
    175                                              op.getOutputMessage(),
    176                                              part,
    177                                              op.getName() + "Response");
    178         part.setElementName(typeQName);
    179         part.setName("parameters");
    180
    181         req.addPart(part);
    182     }
    183
    184     private QName createDocumentType(WSDLBuilder builder,
    185                                      MessageInfo message,
    186                                      Part part,
    187                                      String opName)
    188     {
    189         Element schemaEl = builder.createSchemaType(builder.getInfo().getTargetNamespace());
    190         Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
    191         schemaEl.appendChild(element);
    192
    193         element.addAttribute(new Attribute("name", opName));
    194
    195         Element complex = new Element(AbstractWSDL.complexQ, SoapConstants.XSD);
    196         element.appendChild(complex);
    197
    198         if (message.getMessageParts().size() > 0)
    199         {
    200             Element sequence = createSequence(complex);
    201
    202             writeParametersSchema(builder, message.getMessageParts(), sequence);
    203         }
    204
    205         return new QName(builder.getInfo().getTargetNamespace(), opName);
    206     }
    207
    208     /***
    209      * @param op
    210      * @param sequence
    211      */
    212     private void writeParametersSchema(WSDLBuilder builder,
    213                                        Collection params,
    214                                        Element sequence)
    215     {
    216         for (Iterator itr = params.iterator(); itr.hasNext();)
    217         {
    218             MessagePartInfo param = (MessagePartInfo) itr.next();
    219
    220             Class clazz = param.getTypeClass();
    221             QName pName = param.getName();
    222             SchemaType type = param.getSchemaType();
    223
    224             builder.addDependency(type);
    225             QName schemaType = type.getSchemaType();
    226
    227             String uri = type.getSchemaType().getNamespaceURI();
    228             String prefix = builder.getNamespacePrefix(uri);
    229             builder.addNamespace(prefix, uri);
    230
    231             Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
    232             sequence.appendChild(element);
    233
    234             if (type.isAbstract())
    235             {
    236                 element.addAttribute(new Attribute("name", pName.getLocalPart()));
    237
    238                 element.addAttribute(new Attribute("type",
    239                                                    prefix + ":" + schemaType.getLocalPart()));
    240             }
    241             else
    242             {
    243                 element.addAttribute(new Attribute("ref",  prefix + ":" + schemaType.getLocalPart()));
    244             }
    245
    246             element.addAttribute(new Attribute("minOccurs", "1"));
    247             element.addAttribute(new Attribute("maxOccurs", "1"));
    248         }
    249     }
    250
    251     private Element createSequence(Element complex)
    252     {
    253         Element sequence = new Element(AbstractWSDL.sequenceQ, SoapConstants.XSD);
    254         complex.appendChild(sequence);
    255         return sequence;
    256     }
    257
    258     public Object clone()
    259     {
    260         WrappedBinding binding = new WrappedBinding();
    261         binding.setBindingProvider(getBindingProvider());
    262
    263         return binding;
    264     }
    265 }