View Javadoc

    1   package org.codehaus.xfire.wsdl11.builder;
    2
    3   import java.util.ArrayList;
    4   import java.util.HashMap;
    5   import java.util.Iterator;
    6   import java.util.List;
    7   import java.util.Map;
    8   import java.io.OutputStream;
    9   import java.io.IOException;
    10
    11  import javax.wsdl.Binding;
    12  import javax.wsdl.BindingInput;
    13  import javax.wsdl.BindingOperation;
    14  import javax.wsdl.Definition;
    15  import javax.wsdl.Input;
    16  import javax.wsdl.Message;
    17  import javax.wsdl.Output;
    18  import javax.wsdl.Part;
    19  import javax.wsdl.Port;
    20  import javax.wsdl.PortType;
    21  import javax.wsdl.WSDLException;
    22  import javax.wsdl.extensions.soap.SOAPHeader;
    23  import javax.xml.namespace.QName;
    24
    25  import org.codehaus.xfire.service.MessageHeaderInfo;
    26  import org.codehaus.xfire.service.MessageInfo;
    27  import org.codehaus.xfire.service.MessagePartInfo;
    28  import org.codehaus.xfire.service.OperationInfo;
    29  import org.codehaus.xfire.service.Service;
    30  import org.codehaus.xfire.soap.SoapConstants;
    31  import org.codehaus.xfire.transport.Transport;
    32  import org.codehaus.xfire.transport.TransportManager;
    33  import org.codehaus.xfire.wsdl.SchemaType;
    34  import org.codehaus.xfire.wsdl.WSDLWriter;
    35  import org.codehaus.xfire.wsdl11.WSDL11ParameterBinding;
    36  import org.codehaus.xfire.wsdl11.WSDL11Transport;
    37  import org.codehaus.xfire.XFireRuntimeException;
    38  import org.codehaus.yom.Attribute;
    39  import org.codehaus.yom.Element;
    40
    41  import com.ibm.wsdl.extensions.soap.SOAPHeaderImpl;
    42
    43  /***
    44   * WSDL
    45   *
    46   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
    47   */
    48  public class WSDLBuilder
    49      extends org.codehaus.xfire.wsdl11.builder.AbstractWSDL
    50      implements WSDLWriter
    51  {
    52      private PortType portType;
    53
    54      private Binding binding;
    55
    56      private TransportManager transportManager;
    57
    58      private Map wsdlOps = new HashMap();
    59
    60      private WSDL11ParameterBinding paramBinding;
    61
    62      private List declaredParameters = new ArrayList();
    63
    64      public WSDLBuilder(Service service,
    65                         TransportManager transportManager,
    66                         WSDL11ParameterBinding paramBinding) throws WSDLException
    67      {
    68          super(service);
    69
    70          this.transportManager = transportManager;
    71          this.paramBinding = paramBinding;
    72
    73      }
    74
    75      public void write(OutputStream out) throws IOException
    76      {
    77          try
    78          {
    79              PortType portType = createAbstractInterface();
    80
    81              createConcreteInterface(portType);
    82
    83              writeDocument();
    84          } catch (WSDLException e)
    85          {
    86              throw new XFireRuntimeException("error creating wsdl", e);
    87          }
    88          super.write(out);
    89      }
    90
    91      public PortType createAbstractInterface()
    92          throws WSDLException
    93      {
    94          Service service = getService();
    95          Definition def = getDefinition();
    96
    97          QName portName = new QName(getInfo().getTargetNamespace(), getInfo().getPortType());
    98
    99          portType = def.createPortType();
    100         portType.setQName(portName);
    101         portType.setUndefined(false);
    102         def.addPortType(portType);
    103
    104         // Create Abstract operations
    105         for (Iterator itr = service.getServiceInfo().getOperations().iterator(); itr.hasNext();)
    106         {
    107             OperationInfo op = (OperationInfo) itr.next();
    108
    109             // Create input message
    110             Message req = createInputMessage(op);
    111             def.addMessage(req);
    112
    113             // Create output message if we have an out MEP
    114             Message res = null;
    115             if (op.getMEP().equals(SoapConstants.MEP_ROBUST_IN_OUT))
    116             {
    117                 res = createOutputMessage(op);
    118                 def.addMessage(res);
    119             }
    120
    121             javax.wsdl.Operation wsdlOp = createOperation(op, req, res);
    122             wsdlOp.setUndefined(false);
    123             portType.addOperation(wsdlOp);
    124
    125             wsdlOps.put(op.getName(), wsdlOp);
    126         }
    127
    128         return portType;
    129     }
    130
    131     public void createConcreteInterface(PortType portType)
    132     {
    133         Service service = getService();
    134         Definition def = getDefinition();
    135
    136         QName name = new QName(getInfo().getTargetNamespace(), getInfo().getServiceName());
    137
    138         // Create a concrete instance for each transport.
    139         javax.wsdl.Service wsdlService = def.createService();
    140         wsdlService.setQName(name);
    141
    142         for (Iterator itr = transportManager.getTransports(service.getName()).iterator(); itr.hasNext();)
    143         {
    144             Object transportObj = (Transport) itr.next();
    145
    146             if (!(transportObj instanceof WSDL11Transport))
    147             {
    148                 continue;
    149             }
    150
    151             WSDL11Transport transport = (WSDL11Transport) transportObj;
    152
    153             Binding transportBinding = transport.createBinding(this, portType, paramBinding);
    154
    155             for (Iterator oitr = service.getServiceInfo().getOperations().iterator(); oitr.hasNext();)
    156             {
    157                 // todo: move out of the first loop, we'll be creating req/res
    158                 // multiple times otherwise
    159                 OperationInfo op = (OperationInfo) oitr.next();
    160
    161                 javax.wsdl.Operation wsdlOp = (javax.wsdl.Operation) wsdlOps.get(op.getName());
    162
    163                 BindingOperation bop = transport.createBindingOperation(this, portType, wsdlOp, paramBinding);
    164                 transportBinding.addBindingOperation(bop);
    165
    166                 createHeaders(op, bop);
    167             }
    168
    169             Port transportPort = transport.createPort(this, transportBinding);
    170
    171             def.addBinding(transportBinding);
    172             wsdlService.addPort(transportPort);
    173         }
    174
    175         def.addService(wsdlService);
    176
    177     }
    178
    179     private void createHeaders(OperationInfo op, BindingOperation bop)
    180     {
    181         List inputHeaders = op.getInputMessage().getMessageHeaders();
    182         if (inputHeaders.size() == 0)
    183         {
    184             return;
    185         }
    186
    187         BindingInput bindingInput = bop.getBindingInput();
    188
    189         Message reqHeaders = createHeaderMessages(op.getInputMessage());
    190         getDefinition().addMessage(reqHeaders);
    191
    192         for (Iterator headerItr = reqHeaders.getParts().values().iterator(); headerItr.hasNext();)
    193         {
    194             Part headerInfo = (Part) headerItr.next();
    195
    196             SOAPHeader soapHeader = new SOAPHeaderImpl();
    197             soapHeader.setMessage(reqHeaders.getQName());
    198             soapHeader.setPart(headerInfo.getName());
    199             soapHeader.setUse(paramBinding.getUse());
    200
    201             bindingInput.addExtensibilityElement(soapHeader);
    202         }
    203     }
    204
    205     private Message createOutputMessage(OperationInfo op)
    206     {
    207         // response message
    208         Message res = getDefinition().createMessage();
    209         res.setQName(new QName(getInfo().getTargetNamespace(), op.getName() + "Response"));
    210
    211         res.setUndefined(false);
    212
    213         paramBinding.createOutputParts(this, res, op);
    214
    215         return res;
    216     }
    217
    218     private Message createInputMessage(OperationInfo op)
    219     {
    220         Message req = getDefinition().createMessage();
    221         req.setQName(new QName(getInfo().getTargetNamespace(), op.getName() + "Request"));
    222         req.setUndefined(false);
    223
    224         paramBinding.createInputParts(this, req, op);
    225
    226         return req;
    227     }
    228
    229     private Message createHeaderMessages(MessageInfo msgInfo)
    230     {
    231         Message msg = getDefinition().createMessage();
    232
    233         msg.setQName(new QName(getInfo().getTargetNamespace(), msgInfo.getName().getLocalPart() + "Headers"));
    234         msg.setUndefined(false);
    235
    236         for (Iterator itr = msgInfo.getMessageHeaders().iterator(); itr.hasNext();)
    237         {
    238             MessageHeaderInfo header = (MessageHeaderInfo) itr.next();
    239
    240             Part part = createPart(header);
    241
    242             msg.addPart(part);
    243         }
    244
    245         return msg;
    246     }
    247
    248     public Part createPart(MessageHeaderInfo header)
    249     {
    250         return createPart(header.getName(), header.getTypeClass(), header.getSchemaType());
    251     }
    252
    253     public Part createPart(MessagePartInfo part)
    254     {
    255         return createPart(part.getName(), part.getTypeClass(), part.getSchemaType());
    256     }
    257
    258     public Part createPart(QName pName, Class clazz, SchemaType type)
    259     {
    260         addDependency(type);
    261
    262         QName schemaTypeName = type.getSchemaType();
    263
    264         Part part = getDefinition().createPart();
    265         part.setName(pName.getLocalPart());
    266
    267         if (!type.isAbstract())
    268         {
    269             String prefix = getNamespacePrefix(schemaTypeName.getNamespaceURI());
    270             addNamespace(prefix, schemaTypeName.getNamespaceURI());
    271
    272             part.setElementName(schemaTypeName);
    273
    274             return part;
    275         }
    276
    277         if (!declaredParameters.contains(pName))
    278         {
    279             Element schemaEl = createSchemaType(getInfo().getTargetNamespace());
    280
    281             Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
    282             schemaEl.appendChild(element);
    283
    284             String prefix = getNamespacePrefix(schemaTypeName.getNamespaceURI());
    285             addNamespace(prefix, schemaTypeName.getNamespaceURI());
    286
    287             if (type.isAbstract())
    288             {
    289                 element.addAttribute(new Attribute("name", pName.getLocalPart()));
    290                 element.addAttribute(new Attribute("type",
    291                                                    prefix + ":" + schemaTypeName.getLocalPart()));
    292             }
    293
    294             declaredParameters.add(pName);
    295         }
    296
    297         part.setElementName(pName);
    298
    299         return part;
    300     }
    301
    302     public javax.wsdl.Operation createOperation(OperationInfo op, Message req, Message res)
    303     {
    304         Definition def = getDefinition();
    305         javax.wsdl.Operation wsdlOp = def.createOperation();
    306
    307         Input input = def.createInput();
    308         input.setMessage(req);
    309         input.setName(req.getQName().getLocalPart());
    310         wsdlOp.setInput(input);
    311
    312         if (res != null)
    313         {
    314             Output output = def.createOutput();
    315             output.setMessage(res);
    316             output.setName(res.getQName().getLocalPart());
    317             wsdlOp.setOutput(output);
    318         }
    319
    320         wsdlOp.setName(op.getName());
    321
    322         return wsdlOp;
    323     }
    324 }