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.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
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
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><service></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 }