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 }