1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
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
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><service></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 }