View Javadoc

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