View Javadoc

    1   package org.codehaus.xfire.aegis;
    2
    3   import java.util.Iterator;
    4
    5   import javax.xml.namespace.QName;
    6   import javax.xml.stream.XMLStreamReader;
    7   import javax.xml.stream.XMLStreamWriter;
    8
    9   import org.codehaus.xfire.MessageContext;
    10  import org.codehaus.xfire.XFireRuntimeException;
    11  import org.codehaus.xfire.aegis.stax.ElementReader;
    12  import org.codehaus.xfire.aegis.stax.ElementWriter;
    13  import org.codehaus.xfire.aegis.type.DefaultTypeMappingRegistry;
    14  import org.codehaus.xfire.aegis.type.Type;
    15  import org.codehaus.xfire.aegis.type.TypeMapping;
    16  import org.codehaus.xfire.aegis.type.TypeMappingRegistry;
    17  import org.codehaus.xfire.aegis.yom.YOMReader;
    18  import org.codehaus.xfire.aegis.yom.YOMWriter;
    19  import org.codehaus.xfire.fault.XFireFault;
    20  import org.codehaus.xfire.service.MessageHeaderInfo;
    21  import org.codehaus.xfire.service.MessagePartContainer;
    22  import org.codehaus.xfire.service.MessagePartInfo;
    23  import org.codehaus.xfire.service.OperationInfo;
    24  import org.codehaus.xfire.service.Service;
    25  import org.codehaus.xfire.service.binding.AbstractBinding;
    26  import org.codehaus.xfire.service.binding.BindingProvider;
    27  import org.codehaus.xfire.soap.SoapConstants;
    28  import org.codehaus.yom.Element;
    29
    30  /***
    31   * A BindingProvider for the Aegis type system.
    32   *
    33   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
    34   */
    35  public class AegisBindingProvider
    36      implements BindingProvider
    37  {
    38      public static final String TYPE_MAPPING_KEY = "type.mapping";
    39      public static final String ENCODING_URI_KEY = "type.encodingUri";
    40
    41      private TypeMappingRegistry registry;
    42      private boolean writeOuter = true;
    43
    44      public AegisBindingProvider()
    45      {
    46          this(new DefaultTypeMappingRegistry(true));
    47      }
    48
    49      public AegisBindingProvider(TypeMappingRegistry registry)
    50      {
    51          this.registry = registry;
    52      }
    53
    54      public boolean isWriteOuter()
    55      {
    56          return writeOuter;
    57      }
    58
    59      public void setWriteOuter(boolean writeOuter)
    60      {
    61          this.writeOuter = writeOuter;
    62      }
    63
    64      /***
    65       * Creates a type mapping for this class and registers it with the TypeMappingRegistry. This needs to be called
    66       * before initializeOperations().
    67       */
    68      public void initialize(Service endpoint)
    69      {
    70          String encodingStyle = (String) endpoint.getProperty(ENCODING_URI_KEY);
    71
    72          if (encodingStyle == null)
    73          {
    74              AbstractBinding binding = (AbstractBinding) endpoint.getBinding();
    75              if (binding.getUse().equals(SoapConstants.USE_ENCODED))
    76              {
    77                  encodingStyle = endpoint.getSoapVersion().getSoapEncodingStyle();
    78              }
    79              else
    80              {
    81                  encodingStyle = SoapConstants.XSD;
    82              }
    83          }
    84
    85          endpoint.setProperty(ENCODING_URI_KEY, encodingStyle);
    86          final TypeMapping tm = registry.createTypeMapping(encodingStyle, true);
    87
    88          endpoint.setProperty(TYPE_MAPPING_KEY, tm);
    89          registry.register(endpoint.getServiceInfo().getName().getNamespaceURI(), tm);
    90
    91          for (Iterator itr = endpoint.getServiceInfo().getOperations().iterator(); itr.hasNext();)
    92          {
    93              OperationInfo opInfo = (OperationInfo) itr.next();
    94              try
    95              {
    96                  initializeMessage(endpoint, opInfo.getInputMessage());
    97              }
    98              catch(XFireRuntimeException e)
    99              {
    100                 e.prepend("Error initializing parameters for method " + opInfo.getMethod());
    101                 throw e;
    102             }
    103             try
    104             {
    105                 initializeMessage(endpoint, opInfo.getOutputMessage());
    106             }
    107             catch(XFireRuntimeException e)
    108             {
    109                 e.prepend("Error initializing return value for method " + opInfo.getMethod());
    110                 throw e;
    111             }
    112         }
    113     }
    114
    115     protected void initializeMessage(Service service, MessagePartContainer container)
    116     {
    117         for (Iterator itr = container.getMessageHeaders().iterator(); itr.hasNext();)
    118         {
    119             MessageHeaderInfo header = (MessageHeaderInfo) itr.next();
    120
    121             header.setSchemaType(getParameterType(getTypeMapping(service), header));
    122         }
    123
    124         for (Iterator itr = container.getMessageParts().iterator(); itr.hasNext();)
    125         {
    126             MessagePartInfo part = (MessagePartInfo) itr.next();
    127
    128             part.setSchemaType(getParameterType(getTypeMapping(service), part));
    129         }
    130     }
    131
    132     public Object readParameter(MessagePartInfo p, XMLStreamReader xsr, MessageContext context)
    133         throws XFireFault
    134     {
    135         Type type = (Type) p.getSchemaType();
    136
    137         MessageReader reader = new ElementReader(xsr);
    138
    139         return type.readObject(reader, context);
    140     }
    141
    142     public void writeParameter(MessagePartInfo p,
    143                                XMLStreamWriter writer,
    144                                MessageContext context,
    145                                Object value)
    146         throws XFireFault
    147     {
    148         Type type = (Type) p.getSchemaType();
    149
    150         MessageWriter mw;
    151         if (writeOuter)
    152             mw = new ElementWriter(writer, p.getName());
    153         else
    154             mw = new ElementWriter(writer);
    155
    156         type.writeObject(value, mw, context);
    157
    158         if (writeOuter)
    159             mw.close();
    160     }
    161
    162     private Type getParameterType(TypeMapping tm, MessagePartInfo param)
    163     {
    164         Type type = tm.getType(param.getName());
    165
    166         if (type == null && tm.isRegistered(param.getTypeClass()))
    167         {
    168             type = tm.getType(param.getTypeClass());
    169         }
    170
    171         if (type == null)
    172         {
    173             OperationInfo op = param.getContainer().getOperation();
    174
    175             int index = -1;
    176
    177             if (op.getInputMessage().getMessageParts().contains(param))
    178                 index = param.getIndex();
    179
    180             /* Note: we are not registering the type here, because it is an anonymous
    181              * type. Potentially there could be many schema types with this name. For example,
    182              * there could be many ns:in0 paramters.
    183              */
    184             type = tm.getTypeCreator().createType(op.getMethod(), index);
    185             type.setTypeMapping(tm);
    186         }
    187
    188         return type;
    189     }
    190
    191     private Type getParameterType(TypeMapping tm, MessageHeaderInfo param)
    192     {
    193         Type type = tm.getType(param.getName());
    194
    195         if (type == null && tm.isRegistered(param.getTypeClass()))
    196         {
    197             type = tm.getType(param.getTypeClass());
    198         }
    199
    200         if (type == null)
    201         {
    202             OperationInfo op = param.getContainer().getOperation();
    203
    204             int index = -1;
    205
    206             if (op.getInputMessage().getMessageHeaders().contains(param))
    207                 index = param.getIndex();
    208
    209             /* Note: we are not registering the type here, because it is an anonymous
    210              * type. Potentially there could be many schema types with this name. For example,
    211              * there could be many ns:in0 paramters.
    212              */
    213             type = tm.getTypeCreator().createType(op.getMethod(), index);
    214             type.setTypeMapping(tm);
    215         }
    216
    217         return type;
    218     }
    219
    220     public static TypeMapping getTypeMapping(Service service)
    221     {
    222         return (TypeMapping) service.getProperty(TYPE_MAPPING_KEY);
    223     }
    224
    225     public Object readHeader(MessageHeaderInfo p, MessageContext context)
    226         throws XFireFault
    227     {
    228         Type type = (Type) p.getSchemaType();
    229
    230         QName name = p.getName();
    231         Element headers = context.getExchange().getInMessage().getHeader();
    232         Element header = headers.getFirstChildElement(name.getLocalPart(), name.getNamespaceURI());
    233
    234         if (header == null) return null;
    235
    236         return type.readObject(new YOMReader(header), context);
    237     }
    238
    239     public void writeHeader(MessagePartInfo p, MessageContext context, Object value)
    240         throws XFireFault
    241     {
    242         Type type = (Type) p.getSchemaType();
    243
    244         MessageWriter mw = new YOMWriter(context.getOutMessage().getHeader());
    245
    246         type.writeObject(value, mw, context);
    247
    248         mw.close();
    249     }
    250
    251 }