View Javadoc

    1   /*
    2    *
    3    * The Seasar Software License, Version 1.1
    4    *
    5    * Copyright (c) 2003-2004 The Seasar Project. All rights reserved.
    6    *
    7    * Redistribution and use in source and binary forms, with or
    8    * without modification, are permitted provided that the following
    9    * conditions are met:
    10   *
    11   * 1. Redistributions of source code must retain the above
    12   *    copyright notice, this list of conditions and the following
    13   *    disclaimer.
    14   *
    15   * 2. Redistributions in binary form must reproduce the above
    16   *    copyright notice, this list of conditions and the following
    17   *    disclaimer in the documentation and/or other materials provided
    18   *    with the distribution.
    19   *
    20   * 3. The end-user documentation included with the redistribution,
    21   *    if any, must include the following acknowledgement:
    22   *    "This product includes software developed by the
    23   *    Seasar Project (http://www.seasar.org/)."
    24   *    Alternately, this acknowledgement may appear in the software
    25   *    itself, if and wherever such third-party acknowledgements
    26   *    normally appear.
    27   *
    28   * 4. Neither the name "The Seasar Project" nor the names of its
    29   *    contributors may be used to endorse or promote products derived
    30   *    from this software without specific prior written permission of
    31   *    the Seasar Project.
    32   *
    33   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR
    34   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    35   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    36   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE SEASAR PROJECT
    37   * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
    38   * INCIDENTAL,SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    39   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    40   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    41   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    42   * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING
    43   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    44   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    45   */
    46  package org.seasar.remoting.axis.deployment;
    47
    48  import java.lang.reflect.Method;
    49  import java.util.ArrayList;
    50  import java.util.HashMap;
    51  import java.util.Iterator;
    52  import java.util.List;
    53  import java.util.Map;
    54
    55  import javax.xml.namespace.QName;
    56  import javax.xml.rpc.encoding.TypeMapping;
    57
    58  import org.apache.axis.constants.Use;
    59  import org.apache.axis.deployment.wsdd.WSDDConstants;
    60  import org.apache.axis.deployment.wsdd.WSDDException;
    61  import org.apache.axis.deployment.wsdd.WSDDService;
    62  import org.apache.axis.deployment.wsdd.WSDDTypeMapping;
    63  import org.apache.axis.description.JavaServiceDesc;
    64  import org.apache.axis.encoding.TypeMappingDelegate;
    65  import org.apache.axis.encoding.TypeMappingRegistry;
    66  import org.apache.axis.providers.java.JavaProvider;
    67  import org.apache.axis.wsdl.fromJava.Namespaces;
    68  import org.apache.axis.wsdl.fromJava.Types;
    69  import org.seasar.framework.container.ComponentDef;
    70  import org.seasar.framework.message.MessageFormatter;
    71  import org.seasar.framework.util.StringUtil;
    72  import org.seasar.remoting.axis.S2AxisConstants;
    73  import org.seasar.remoting.axis.ServiceDef;
    74  import org.seasar.remoting.axis.TypeMappingDef;
    75  import org.w3c.dom.Element;
    76
    77  /***
    78   * S2によりインスタンス管理されるサービスのWSDDによる表現です。
    79   *
    80   * @author koichik
    81   */
    82  public class WSDDS2Service extends WSDDService {
    83      //static fields
    84      protected static final Map providerMapping = new HashMap();
    85      static {
    86          providerMapping.put(PROVIDER_RPC, S2AxisConstants.PROVIDER_S2RPC);
    87          providerMapping.put(PROVIDER_MSG, S2AxisConstants.PROVIDER_S2MSG);
    88      }
    89
    90      //instance fields
    91      protected final ComponentDef componentDef;
    92
    93      /***
    94       * コンポーネント定義からインスタンスを構築します。
    95       *
    96       * @param componentDef
    97       *            コンポーネント定義
    98       * @throws WSDDException
    99       *             インスタンスの構築に失敗した場合にスローされます。
    100      */
    101     public WSDDS2Service(final ComponentDef componentDef) throws WSDDException {
    102         this(componentDef, new ServiceDef());
    103     }
    104
    105     /***
    106      * コンポーネント定義とサービス定義からインスタンスを構築します。
    107      *
    108      * @param componentDef
    109      *            コンポーネント定義
    110      * @param serviceDef
    111      *            サービス定義
    112      * @throws WSDDException
    113      *             インスタンスの構築に失敗した場合にスローされます。
    114      */
    115     public WSDDS2Service(final ComponentDef componentDef, final ServiceDef serviceDef)
    116             throws WSDDException {
    117         this.componentDef = componentDef;
    118
    119         final String name = getName();
    120         setQName(new QName(name));
    121
    122         final JavaServiceDesc serviceDesc = (JavaServiceDesc) getServiceDesc();
    123         serviceDesc.setName(name);
    124
    125         Class serviceType = getServiceClass(serviceDef);
    126         if (serviceType == null) {
    127             serviceType = componentDef.getComponentClass();
    128         }
    129         if (serviceType == null) {
    130             throw new WSDDException(MessageFormatter.getSimpleMessage("EAXS0006",
    131                     new Object[] { name }));
    132         }
    133         setParameter(JavaProvider.OPTION_CLASSNAME, serviceType.getName());
    134
    135         setProviderQName(new QName(WSDDConstants.URI_WSDD_JAVA, getS2Provider(serviceDef
    136                 .getProvider())));
    137
    138         final String allowedMethods = serviceDef.getAllowedMethods();
    139         if (!StringUtil.isEmpty(allowedMethods)) {
    140             setParameter(JavaProvider.OPTION_ALLOWEDMETHODS, allowedMethods);
    141         }
    142
    143         final Iterator typeMappingDefs = serviceDef.getTypeMappings();
    144         while (typeMappingDefs.hasNext()) {
    145             final TypeMappingDef typeMappingDef = (TypeMappingDef) typeMappingDefs.next();
    146             addTypeMapping(createWSDDTypeMapping(typeMappingDef));
    147         }
    148
    149         initTMR();
    150         validateDescriptors();
    151
    152         final TypeMappingRegistry tmr = serviceDesc.getTypeMappingRegistry();
    153         TypeMapping tm = tmr.getTypeMapping(Use.DEFAULT.getEncoding());
    154         ((TypeMappingDelegate) tm).setDoAutoTypes(true);
    155     }
    156
    157     /***
    158      * コンポーネント定義とWSDDファイル(XML)のDOMツリーからインスタンスを構築します。 <br>
    159      * WSDD中の <code>&lt;service&gt;</code> 要素の <code>provider</code>
    160      * 属性で指定されたプロバイダを対応するS2Axisのプロバイダに変更します。
    161      *
    162      * @param componentDef
    163      *            コンポーネント定義
    164      * @param serviceElement
    165      *            WSDDファイル(XML)のDOMツリー
    166      * @throws WSDDException
    167      *             インスタンスの構築に失敗した場合にスローされます。
    168      */
    169     public WSDDS2Service(final ComponentDef componentDef, final Element serviceElement)
    170             throws WSDDException {
    171         super(serviceElement);
    172         this.componentDef = componentDef;
    173         final String provider = getProviderQName().getLocalPart();
    174         setProviderQName(new QName(WSDDConstants.URI_WSDD_JAVA, getS2Provider(provider)));
    175     }
    176
    177     /***
    178      * コンポーネント定義を返します。
    179      *
    180      * @return コンポーネント定義
    181      */
    182     public ComponentDef getComponentDef() {
    183         return componentDef;
    184     }
    185
    186     /***
    187      * サービス名を返します。 <br>
    188      * サービス名は、コンポーネント定義に名前空間が指定されていれば"名前空間/コンポーネント名"、そうでなければ"コンポーネント名"になります。
    189      *
    190      * @return サービス名
    191      */
    192     protected String getName() {
    193         final String namespace = componentDef.getContainer().getNamespace();
    194         final String componentName = componentDef.getComponentName();
    195         if (StringUtil.isEmpty(namespace)) {
    196             return componentName;
    197         }
    198         return namespace + "/" + componentName;
    199     }
    200
    201     /***
    202      * サービスの型を返します。 <br>
    203      * サービスの型は、サービス定義に型が指定されていればその型、そうでなければコンポーネントの型になります。
    204      * <p>
    205      * コンポーネント型が(インタフェースではなく)実装クラスの場合で、メソッドを定義されたインタフェースを
    206      * 一つだけ実装している場合には、そのインタフェースをサービスの型とします。 <br>
    207      * メソッドが定義されたインタフェースを複数実装している場合でかつ、サービス定義に
    208      * 公開するメソッドが指定されていない場合には、インタフェースに定義されたメソッドの名前をサービス定義の公開するメソッドに設定します。
    209      * </p>
    210      *
    211      * @param serviceDef
    212      *            サービス定義
    213      * @return サービスの型
    214      */
    215     protected Class getServiceClass(final ServiceDef serviceDef) {
    216         Class serviceType = null;
    217         serviceType = serviceDef.getServiceType();
    218         if (serviceType != null) {
    219             return serviceType;
    220         }
    221
    222         serviceType = componentDef.getComponentClass();
    223         if (serviceType == null) {
    224             componentDef.getComponent().getClass();
    225         }
    226
    227         if (!serviceType.isInterface()) {
    228             final Class[] interfaces = serviceType.getInterfaces();
    229             final List interfaceList = new ArrayList();
    230             final StringBuffer buf = new StringBuffer(200);
    231             for (int i = 0; i < interfaces.length; ++i) {
    232                 final Method[] methods = interfaces[i].getMethods();
    233                 if (methods.length > 0) {
    234                     interfaceList.add(interfaces[i]);
    235                     for (int j = 0; j < methods.length; ++j) {
    236                         buf.append(methods[j].getName()).append(" ");
    237                     }
    238                 }
    239             }
    240
    241             switch (interfaceList.size()) {
    242             case 0:
    243                 break;
    244             case 1:
    245                 serviceType = (Class) interfaceList.get(0);
    246                 break;
    247             default:
    248                 if (serviceDef.getAllowedMethods() == null) {
    249                     serviceDef.setAllowedMethods(new String(buf));
    250                 }
    251             }
    252         }
    253         return serviceType;
    254     }
    255
    256     /***
    257      * Axisのプロバイダ名に対応するS2Axis用のプロバイダ名を返します。
    258      *
    259      * @param provider
    260      *            Axis標準のプロバイダ名
    261      * @return S2Axis用のプロバイダ名
    262      * @throws WSDDException
    263      *             Axisのプロバイダ名対応するS2Axisのプロバイダがない場合にスローされます
    264      */
    265     protected String getS2Provider(final String provider) throws WSDDException {
    266         final String s2Provider = (String) providerMapping.get(provider);
    267         if (s2Provider == null) {
    268             throw new WSDDException(provider);
    269         }
    270         return s2Provider;
    271     }
    272
    273     /***
    274      * WSDDタイプマッピングを作成して返します。
    275      *
    276      * @param typeMappingDef
    277      *            タイプマッピング定義
    278      * @return WSDDタイプマッピング
    279      */
    280     protected WSDDTypeMapping createWSDDTypeMapping(final TypeMappingDef typeMappingDef) {
    281         final WSDDTypeMapping wsddTypeMapping = new WSDDTypeMapping();
    282
    283         final Class type = typeMappingDef.getType();
    284         wsddTypeMapping.setLanguageSpecificType(typeMappingDef.getType());
    285
    286         wsddTypeMapping.setQName(createQNameOfType(type, typeMappingDef.getNamespaceURI(),
    287                 typeMappingDef.getLocalPart(), typeMappingDef.getNamespacePrefix()));
    288
    289         wsddTypeMapping.setSerializer(typeMappingDef.getSerializer());
    290         wsddTypeMapping.setDeserializer(typeMappingDef.getDeserializer());
    291
    292         wsddTypeMapping.setEncodingStyle(typeMappingDef.getEncodingStyle());
    293
    294         return wsddTypeMapping;
    295     }
    296
    297     /***
    298      * XML型のQNameを作成して返します。
    299      *
    300      * @param type
    301      *            Java型
    302      * @param namespaceURI
    303      *            XML型の名前空間URI。省略するとJava型のパッケージ名から導出されます
    304      * @param localPart
    305      *            XML型のローカル名。省略するとJava型のクラス名が使われます
    306      * @param namespacePrefix
    307      *            XML型の名前空間接頭辞。省略するとデフォルト名前空間になります
    308      * @return XML型のQName
    309      */
    310     protected QName createQNameOfType(final Class type, String namespaceURI, String localPart,
    311             final String namespacePrefix) {
    312         if (StringUtil.isEmpty(namespaceURI)) {
    313             namespaceURI = Namespaces.makeNamespace(type.getName());
    314         }
    315
    316         if (StringUtil.isEmpty(localPart)) {
    317             localPart = Types.getLocalNameFromFullName(type.getName());
    318         }
    319
    320         return new QName(namespaceURI, localPart, namespacePrefix);
    321     }
    322 }