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.STAXUtils;
    26  import org.codehaus.xfire.util.stax.DepthXMLStreamReader;
    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 element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
    190
    191         element.addAttribute(new Attribute("name", opName));
    192
    193         Element complex = new Element(AbstractWSDL.complexQ, SoapConstants.XSD);
    194         element.appendChild(complex);
    195
    196         if (message.getMessageParts().size() > 0)
    197         {
    198             Element sequence = createSequence(complex);
    199
    200             writeParametersSchema(builder, message.getMessageParts(), sequence);
    201         }
    202
    203         Element schemaEl = builder.createSchemaType(builder.getInfo().getTargetNamespace());
    204         schemaEl.appendChild(element);
    205
    206         return new QName(builder.getInfo().getTargetNamespace(), opName);
    207     }
    208
    209     /***
    210      * @param op
    211      * @param sequence
    212      */
    213     private void writeParametersSchema(WSDLBuilder builder,
    214                                        Collection params,
    215                                        Element sequence)
    216     {
    217         for (Iterator itr = params.iterator(); itr.hasNext();)
    218         {
    219             MessagePartInfo param = (MessagePartInfo) itr.next();
    220
    221             QName pName = param.getName();
    222             SchemaType type = param.getSchemaType();
    223
    224             builder.addDependency(type);
    225             QName schemaType = type.getSchemaType();
    226
    227             builder.addNamespaceImport(builder.getService().getServiceInfo().getName().getNamespaceURI(),
    228                                        schemaType.getNamespaceURI());
    229
    230             String uri = type.getSchemaType().getNamespaceURI();
    231             String prefix = builder.getNamespacePrefix(uri);
    232             builder.addNamespace(prefix, uri);
    233
    234             Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
    235             sequence.appendChild(element);
    236
    237             if (type.isAbstract())
    238             {
    239                 element.addAttribute(new Attribute("name", pName.getLocalPart()));
    240
    241                 element.addAttribute(new Attribute("type",
    242                                                    prefix + ":" + schemaType.getLocalPart()));
    243             }
    244             else
    245             {
    246                 element.addAttribute(new Attribute("ref",  prefix + ":" + schemaType.getLocalPart()));
    247             }
    248
    249             element.addAttribute(new Attribute("minOccurs", "1"));
    250             element.addAttribute(new Attribute("maxOccurs", "1"));
    251         }
    252     }
    253
    254     private Element createSequence(Element complex)
    255     {
    256         Element sequence = new Element(AbstractWSDL.sequenceQ, SoapConstants.XSD);
    257         complex.appendChild(sequence);
    258         return sequence;
    259     }
    260
    261     public Object clone()
    262     {
    263         WrappedBinding binding = new WrappedBinding();
    264         binding.setBindingProvider(getBindingProvider());
    265
    266         return binding;
    267     }
    268 }