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;
59  import org.apache.axis.constants.Use;
60  import org.apache.axis.deployment.wsdd.WSDDConstants;
61  import org.apache.axis.deployment.wsdd.WSDDException;
62  import org.apache.axis.deployment.wsdd.WSDDService;
63  import org.apache.axis.deployment.wsdd.WSDDTypeMapping;
64  import org.apache.axis.description.JavaServiceDesc;
65  import org.apache.axis.encoding.TypeMappingDelegate;
66  import org.apache.axis.encoding.TypeMappingRegistry;
67  import org.apache.axis.providers.java.JavaProvider;
68  import org.apache.axis.wsdl.fromJava.Namespaces;
69  import org.apache.axis.wsdl.fromJava.Types;
70  import org.seasar.framework.container.ComponentDef;
71  import org.seasar.framework.message.MessageFormatter;
72  import org.seasar.framework.util.StringUtil;
73  import org.seasar.remoting.axis.S2AxisConstants;
74  import org.seasar.remoting.axis.ServiceDef;
75  import org.seasar.remoting.axis.TypeMappingDef;
76  import org.w3c.dom.Element;
77  
78  /***
79   * S2によりインスタンス管理されるサービスのWSDDによる表現です。
80   * 
81   * @author koichik
82   */
83  public class WSDDS2Service extends WSDDService {
84      //static fields
85      protected static final Map providerMapping = new HashMap();
86      static {
87          providerMapping.put(PROVIDER_RPC, S2AxisConstants.PROVIDER_S2RPC);
88          providerMapping.put(PROVIDER_RPC, S2AxisConstants.PROVIDER_S2RPC);
89      }
90  
91      //instance fields
92      protected ComponentDef componentDef;
93  
94      /***
95       * コンポーネント定義からインスタンスを構築します。
96       * 
97       * @param componentDef
98       *            コンポーネント定義
99       * @throws WSDDException
100      *             インスタンスの構築に失敗した場合にスローされます。
101      */
102     public WSDDS2Service(final ComponentDef componentDef) throws WSDDException {
103         this(componentDef, new ServiceDef());
104     }
105 
106     /***
107      * コンポーネント定義とサービス定義からインスタンスを構築します。
108      * 
109      * @param componentDef
110      *            コンポーネント定義
111      * @param serviceDef
112      *            サービス定義
113      * @throws WSDDException
114      *             インスタンスの構築に失敗した場合にスローされます。
115      */
116     public WSDDS2Service(final ComponentDef componentDef, final ServiceDef serviceDef)
117             throws WSDDException {
118         this.componentDef = componentDef;
119 
120         final String name = getName();
121         setQName(new QName(name));
122 
123         final JavaServiceDesc serviceDesc = (JavaServiceDesc) getServiceDesc();
124         serviceDesc.setName(name);
125 
126         Class serviceType = getServiceClass(serviceDef);
127         if (serviceType == null) {
128             serviceType = componentDef.getComponentClass();
129         }
130         if (serviceType == null) {
131             throw new WSDDException(MessageFormatter.getSimpleMessage("EAXS0006",
132                     new Object[] { name }));
133         }
134         setParameter(JavaProvider.OPTION_CLASSNAME, serviceType.getName());
135 
136         setProviderQName(new QName(WSDDConstants.URI_WSDD_JAVA, getS2Provider(serviceDef
137                 .getProvider())));
138 
139         final String allowedMethods = serviceDef.getAllowedMethods();
140         if (!StringUtil.isEmpty(allowedMethods)) {
141             setParameter(JavaProvider.OPTION_ALLOWEDMETHODS, allowedMethods);
142         }
143 
144         final Iterator typeMappingDefs = serviceDef.getTypeMappings();
145         while (typeMappingDefs.hasNext()) {
146             final TypeMappingDef typeMappingDef = (TypeMappingDef) typeMappingDefs.next();
147             addTypeMapping(createWSDDTypeMapping(typeMappingDef));
148         }
149 
150         initTMR();
151         validateDescriptors();
152 
153         final TypeMappingRegistry tmr = serviceDesc.getTypeMappingRegistry();
154         TypeMapping tm = tmr.getTypeMapping(Use.DEFAULT.getEncoding());
155         ((TypeMappingDelegate) tm).setDoAutoTypes(true);
156     }
157 
158     /***
159      * コンポーネント定義とWSDDファイル(XML)のDOMツリーからインスタンスを構築します。 <br>
160      * WSDD中の <code>&lt;service&gt;</code> 要素の <code>provider</code>
161      * 属性で指定されたプロバイダを対応するS2Axisのプロバイダに変更します。
162      * 
163      * @param componentDef
164      *            コンポーネント定義
165      * @param serviceElement
166      *            WSDDファイル(XML)のDOMツリー
167      * @throws WSDDException
168      *             インスタンスの構築に失敗した場合にスローされます。
169      */
170     public WSDDS2Service(final ComponentDef componentDef, final Element serviceElement)
171             throws WSDDException {
172         super(serviceElement);
173         this.componentDef = componentDef;
174         final String provider = getProviderQName().getLocalPart();
175         setProviderQName(new QName(WSDDConstants.URI_WSDD_JAVA, getS2Provider(provider)));
176     }
177 
178     /***
179      * コンポーネント定義を返します。
180      * 
181      * @return コンポーネント定義
182      */
183     public ComponentDef getComponentDef() {
184         return componentDef;
185     }
186 
187     /***
188      * サービス名を返します。 <br>
189      * サービス名は、コンポーネント定義に名前空間が指定されていれば"名前空間/コンポーネント名"、そうでなければ"コンポーネント名"になります。
190      * 
191      * @return サービス名
192      */
193     protected String getName() {
194         final String namespace = componentDef.getContainer().getNamespace();
195         final String componentName = componentDef.getComponentName();
196         if (StringUtil.isEmpty(namespace)) {
197             return componentName;
198         }
199         return namespace + "/" + componentName;
200     }
201 
202     /***
203      * サービスの型を返します。 <br>
204      * サービスの型は、サービス定義に型が指定されていればその型、そうでなければコンポーネントの型になります。
205      * <p>
206      * コンポーネント型が(インタフェースではなく)実装クラスの場合で、メソッドを定義されたインタフェースを
207      * 一つだけ実装している場合には、そのインタフェースをサービスの型とします。 <br>
208      * メソッドが定義されたインタフェースを複数実装している場合でかつ、サービス定義に
209      * 公開するメソッドが指定されていない場合には、インタフェースに定義されたメソッドの名前をサービス定義の公開するメソッドに設定します。
210      * </p>
211      * 
212      * @param serviceDef
213      *            サービス定義
214      * @return サービスの型
215      */
216     protected Class getServiceClass(final ServiceDef serviceDef) {
217         Class serviceType = null;
218         serviceType = serviceDef.getServiceType();
219         if (serviceType != null) {
220             return serviceType;
221         }
222 
223         serviceType = componentDef.getComponentClass();
224         if (serviceType == null) {
225             componentDef.getComponent().getClass();
226         }
227 
228         if (!serviceType.isInterface()) {
229             final Class[] interfaces = serviceType.getInterfaces();
230             final List interfaceList = new ArrayList();
231             final StringBuffer buf = new StringBuffer(200);
232             for (int i = 0; i < interfaces.length; ++i) {
233                 final Method[] methods = interfaces[i].getMethods();
234                 if (methods.length > 0) {
235                     interfaceList.add(interfaces[i]);
236                     for (int j = 0; j < methods.length; ++j) {
237                         buf.append(methods[j].getName()).append(" ");
238                     }
239                 }
240             }
241 
242             switch (interfaceList.size()) {
243                 case 0:
244                     break;
245                 case 1:
246                     serviceType = (Class) interfaceList.get(0);
247                     break;
248                 default:
249                     if (serviceDef.getAllowedMethods() == null) {
250                         serviceDef.setAllowedMethods(new String(buf));
251                     }
252             }
253         }
254         return serviceType;
255     }
256 
257     /***
258      * Axisのプロバイダ名に対応するS2Axis用のプロバイダ名を返します。
259      * 
260      * @param provider
261      *            Axis標準のプロバイダ名
262      * @return S2Axis用のプロバイダ名
263      * @throws WSDDException
264      *             Axisのプロバイダ名対応するS2Axisのプロバイダがない場合にスローされます
265      */
266     protected String getS2Provider(final String provider) throws WSDDException {
267         final String s2Provider = (String) providerMapping.get(provider);
268         if (s2Provider == null) {
269             throw new WSDDException(provider);
270         }
271         return s2Provider;
272     }
273 
274     /***
275      * WSDDタイプマッピングを作成して返します。
276      * 
277      * @param typeMappingDef
278      *            タイプマッピング定義
279      * @return WSDDタイプマッピング
280      */
281     protected WSDDTypeMapping createWSDDTypeMapping(final TypeMappingDef typeMappingDef) {
282         final WSDDTypeMapping wsddTypeMapping = new WSDDTypeMapping();
283 
284         final Class type = typeMappingDef.getType();
285         wsddTypeMapping.setLanguageSpecificType(typeMappingDef.getType());
286 
287         wsddTypeMapping.setQName(createQNameOfType(type, typeMappingDef.getNamespaceURI(),
288                 typeMappingDef.getLocalPart(), typeMappingDef.getNamespacePrefix()));
289 
290         if (typeMappingDef.getSerializer() != null) {
291             wsddTypeMapping.setSerializer(typeMappingDef.getSerializer());
292         }
293         if (typeMappingDef.getDeserializer() != null) {
294             wsddTypeMapping.setDeserializer(typeMappingDef.getDeserializer());
295         }
296 
297         if (typeMappingDef.getEncodingStyle() == null) {
298             wsddTypeMapping.setEncodingStyle(Constants.URI_DEFAULT_SOAP_ENC);
299         }
300         else {
301             wsddTypeMapping.setEncodingStyle(typeMappingDef.getEncodingStyle());
302         }
303 
304         return wsddTypeMapping;
305     }
306 
307     /***
308      * XML型のQNameを作成して返します。
309      * 
310      * @param type
311      *            Java型
312      * @param namespaceURI
313      *            XML型の名前空間URI。省略するとJava型のパッケージ名から導出されます
314      * @param localPart
315      *            XML型のローカル名。省略するとJava型のクラス名が使われます
316      * @param namespacePrefix
317      *            XML型の名前空間接頭辞。省略するとデフォルト名前空間になります
318      * @return XML型のQName
319      */
320     protected QName createQNameOfType(final Class type, String namespaceURI, String localPart,
321             final String namespacePrefix) {
322         if (StringUtil.isEmpty(namespaceURI)) {
323             namespaceURI = Namespaces.makeNamespace(type.getName());
324         }
325 
326         if (StringUtil.isEmpty(localPart)) {
327             localPart = Types.getLocalNameFromFullName(type.getName());
328         }
329 
330         return new QName(namespaceURI, localPart, namespacePrefix);
331     }
332 }