Source code: org/apache/axis/deployment/wsdd/WSDDService.java
1 /*
2 * Copyright 2001-2005 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.apache.axis.deployment.wsdd;
17
18 import org.apache.axis.AxisEngine;
19 import org.apache.axis.AxisFault;
20 import org.apache.axis.ConfigurationException;
21 import org.apache.axis.Constants;
22 import org.apache.axis.EngineConfiguration;
23 import org.apache.axis.FaultableHandler;
24 import org.apache.axis.Handler;
25 import org.apache.axis.MessageContext;
26 import org.apache.axis.attachments.Attachments;
27 import org.apache.axis.attachments.AttachmentsImpl;
28 import org.apache.axis.constants.Style;
29 import org.apache.axis.constants.Use;
30 import org.apache.axis.description.JavaServiceDesc;
31 import org.apache.axis.description.ServiceDesc;
32 import org.apache.axis.encoding.DeserializerFactory;
33 import org.apache.axis.encoding.SerializationContext;
34 import org.apache.axis.encoding.SerializerFactory;
35 import org.apache.axis.encoding.TypeMapping;
36 import org.apache.axis.encoding.TypeMappingRegistry;
37 import org.apache.axis.encoding.TypeMappingRegistryImpl;
38 import org.apache.axis.encoding.ser.ArraySerializerFactory;
39 import org.apache.axis.encoding.ser.BaseDeserializerFactory;
40 import org.apache.axis.encoding.ser.BaseSerializerFactory;
41 import org.apache.axis.handlers.HandlerInfoChainFactory;
42 import org.apache.axis.handlers.soap.SOAPService;
43 import org.apache.axis.providers.java.JavaProvider;
44 import org.apache.axis.utils.Messages;
45 import org.apache.axis.utils.XMLUtils;
46 import org.w3c.dom.Element;
47 import org.xml.sax.helpers.AttributesImpl;
48
49 import javax.xml.namespace.QName;
50 import java.io.IOException;
51 import java.util.ArrayList;
52 import java.util.List;
53 import java.util.StringTokenizer;
54 import java.util.Vector;
55
56 /**
57 * A service represented in WSDD.
58 *
59 * @author Glen Daniels (gdaniels@apache.org)
60 */
61 public class WSDDService
62 extends WSDDTargetedChain
63 implements WSDDTypeMappingContainer
64 {
65 private TypeMappingRegistry tmr = null;
66
67 private Vector faultFlows = new Vector();
68 private Vector typeMappings = new Vector();
69 private Vector operations = new Vector();
70
71 /** Which namespaces should auto-dispatch to this service? */
72 private Vector namespaces = new Vector();
73
74 /** Which roles does this service support? */
75 private List roles = new ArrayList();
76
77 private String descriptionURL;
78
79 /** Style - document, wrapped, message, or RPC (the default) */
80 private Style style = Style.DEFAULT;
81 /** Use - encoded (the default) or literal */
82 private Use use = Use.DEFAULT;
83
84 private transient SOAPService cachedService = null;
85
86 /**
87 * Our provider - used to figure out which Handler we use as a service
88 * pivot (see getInstance() below)
89 */
90 private QName providerQName;
91
92 // private HandlerInfoChainFactory _hiChainFactory;
93 private WSDDJAXRPCHandlerInfoChain _wsddHIchain;
94
95 JavaServiceDesc desc = new JavaServiceDesc();
96
97 /**
98 * Is streaming (i.e. NO high-fidelity recording, deserialize on the fly)
99 * on for this service?
100 */
101 private boolean streaming = false;
102
103 /**
104 * What attachment format should be used?
105 */
106 private int sendType = Attachments.SEND_TYPE_NOTSET;
107
108 /**
109 * Default constructor
110 */
111 public WSDDService()
112 {
113 }
114
115 /**
116 *
117 * @param e (Element) XXX
118 * @throws WSDDException XXX
119 */
120 public WSDDService(Element e)
121 throws WSDDException
122 {
123 super(e);
124
125 desc.setName(getQName().getLocalPart());
126
127 String styleStr = e.getAttribute(ATTR_STYLE);
128 if (styleStr != null && !styleStr.equals("")) {
129 style = Style.getStyle(styleStr, Style.DEFAULT);
130 desc.setStyle(style);
131 providerQName = style.getProvider();
132 }
133
134 String useStr = e.getAttribute(ATTR_USE);
135 if (useStr != null && !useStr.equals("")) {
136 use = Use.getUse(useStr, Use.DEFAULT);
137 desc.setUse(use);
138 } else {
139 if (style != Style.RPC) {
140 // Default to use=literal if not style=RPC
141 use = Use.LITERAL;
142 desc.setUse(use);
143 }
144 }
145
146 String streamStr = e.getAttribute(ATTR_STREAMING);
147 if (streamStr != null && streamStr.equals("on")) {
148 streaming = true;
149 }
150
151 String attachmentStr = e.getAttribute(ATTR_ATTACHMENT_FORMAT);
152 if (attachmentStr != null && !attachmentStr.equals("")) {
153 sendType = AttachmentsImpl.getSendType(attachmentStr);
154 }
155
156 Element [] operationElements = getChildElements(e, ELEM_WSDD_OPERATION);
157 for (int i = 0; i < operationElements.length; i++) {
158 WSDDOperation operation = new WSDDOperation(operationElements[i],
159 desc);
160 addOperation(operation);
161 }
162
163 Element [] typeMappingElements = getChildElements(e, ELEM_WSDD_TYPEMAPPING);
164 for (int i = 0; i < typeMappingElements.length; i++) {
165 WSDDTypeMapping mapping =
166 new WSDDTypeMapping(typeMappingElements[i]);
167 typeMappings.add(mapping);
168 }
169
170 Element [] beanMappingElements = getChildElements(e, ELEM_WSDD_BEANMAPPING);
171 for (int i = 0; i < beanMappingElements.length; i++) {
172 WSDDBeanMapping mapping =
173 new WSDDBeanMapping(beanMappingElements[i]);
174 typeMappings.add(mapping);
175 }
176
177 Element [] arrayMappingElements = getChildElements(e, ELEM_WSDD_ARRAYMAPPING);
178 for (int i = 0; i < arrayMappingElements.length; i++) {
179 WSDDArrayMapping mapping =
180 new WSDDArrayMapping(arrayMappingElements[i]);
181 typeMappings.add(mapping);
182 }
183
184 Element [] namespaceElements = getChildElements(e, ELEM_WSDD_NAMESPACE);
185 for (int i = 0; i < namespaceElements.length; i++) {
186 // Register a namespace for this service
187 String ns = XMLUtils.getChildCharacterData(namespaceElements[i]);
188 namespaces.add(ns);
189 }
190 if (!namespaces.isEmpty())
191 desc.setNamespaceMappings(namespaces);
192
193 Element [] roleElements = getChildElements(e, ELEM_WSDD_ROLE);
194 for (int i = 0; i < roleElements.length; i++) {
195 String role = XMLUtils.getChildCharacterData(roleElements[i]);
196 roles.add(role);
197 }
198
199 Element wsdlElem = getChildElement(e, ELEM_WSDD_WSDLFILE);
200 if (wsdlElem != null) {
201 String fileName = XMLUtils.getChildCharacterData(wsdlElem);
202 desc.setWSDLFile(fileName.trim());
203 }
204
205 Element docElem = getChildElement(e, ELEM_WSDD_DOC);
206 if (docElem != null) {
207 WSDDDocumentation documentation = new WSDDDocumentation(docElem);
208 desc.setDocumentation(documentation.getValue());
209 }
210
211 Element urlElem = getChildElement(e, ELEM_WSDD_ENDPOINTURL);
212 if (urlElem != null) {
213 String endpointURL = XMLUtils.getChildCharacterData(urlElem);
214 desc.setEndpointURL(endpointURL);
215 }
216
217 String providerStr = e.getAttribute(ATTR_PROVIDER);
218 if (providerStr != null && !providerStr.equals("")) {
219 providerQName = XMLUtils.getQNameFromString(providerStr, e);
220 if (WSDDConstants.QNAME_JAVAMSG_PROVIDER.equals(providerQName)) {
221 // Message style if message provider...
222 desc.setStyle(Style.MESSAGE);
223 }
224 }
225
226 // Add in JAX-RPC support for HandlerInfo chains
227 Element hcEl = getChildElement(e, ELEM_WSDD_JAXRPC_CHAIN);
228 if (hcEl != null) {
229 _wsddHIchain = new WSDDJAXRPCHandlerInfoChain(hcEl);
230 }
231
232 // Initialize TypeMappingRegistry
233 initTMR();
234
235 // call to validate standard descriptors for this service
236 validateDescriptors();
237 }
238
239 /**
240 * Initialize a TypeMappingRegistry with the
241 * WSDDTypeMappings.
242 * Note: Extensions of WSDDService may override
243 * initTMR to popluate the tmr with different
244 * type mappings.
245 */
246 protected void initTMR() throws WSDDException
247 {
248 // If not created, construct a tmr
249 // and populate it with the type mappings.
250 if (tmr == null) {
251 createTMR();
252 for (int i=0; i<typeMappings.size(); i++) {
253 deployTypeMapping((WSDDTypeMapping)
254 typeMappings.get(i));
255 }
256 }
257 }
258
259 private void createTMR() {
260 tmr = new TypeMappingRegistryImpl(false);
261 String version = getParameter("typeMappingVersion");
262 ((TypeMappingRegistryImpl)tmr).doRegisterFromVersion(version);
263 }
264
265 /**
266 * This method can be used for dynamic deployment using new WSDDService()
267 * etc. It validates some standard parameters for some standard providers
268 * (if present). Do this before deployment.deployService().
269 */
270 public void validateDescriptors() throws WSDDException
271 {
272 if (tmr == null) {
273 initTMR();
274 }
275 desc.setTypeMappingRegistry(tmr);
276 desc.setTypeMapping(getTypeMapping(desc.getUse().getEncoding()));
277
278 String allowedMethods = getParameter(JavaProvider.OPTION_ALLOWEDMETHODS);
279 if (allowedMethods != null && !"*".equals(allowedMethods)) {
280 ArrayList methodList = new ArrayList();
281 StringTokenizer tokenizer = new StringTokenizer(allowedMethods, " ,");
282 while (tokenizer.hasMoreTokens()) {
283 methodList.add(tokenizer.nextToken());
284 }
285 desc.setAllowedMethods(methodList);
286 }
287 }
288
289 /**
290 * Add a WSDDTypeMapping to the Service.
291 * @param mapping
292 **/
293 public void addTypeMapping(WSDDTypeMapping mapping) {
294 typeMappings.add(mapping);
295 }
296
297 /**
298 * Add a WSDDOperation to the Service.
299 * @param operation the operation to add
300 **/
301 public void addOperation(WSDDOperation operation) {
302 operations.add(operation);
303 desc.addOperationDesc(operation.getOperationDesc());
304 }
305
306 protected QName getElementName()
307 {
308 return QNAME_SERVICE;
309 }
310
311 /**
312 * Get any service description URL which might be associated with this
313 * service.
314 *
315 * @return a String containing a URL, or null.
316 */
317 public String getServiceDescriptionURL()
318 {
319 return descriptionURL;
320 }
321
322 /**
323 * Set the service description URL for this service.
324 *
325 * @param sdUrl a String containing a URL
326 */
327 public void setServiceDescriptionURL(String sdUrl)
328 {
329 descriptionURL = sdUrl;
330 }
331
332 public QName getProviderQName() {
333 return providerQName;
334 }
335
336 public void setProviderQName(QName providerQName) {
337 this.providerQName = providerQName;
338 }
339
340 public ServiceDesc getServiceDesc() {
341 return desc;
342 }
343
344 /**
345 * Get the service style - document or RPC
346 */
347 public Style getStyle() {
348 return style;
349 }
350
351 /**
352 * Set the service style - document or RPC
353 */
354 public void setStyle(Style style) {
355 this.style = style;
356 }
357
358 /**
359 * Get the service use - literal or encoded
360 */
361 public Use getUse() {
362 return use;
363 }
364
365 /**
366 * Set the service use - literal or encoded
367 */
368 public void setUse(Use use) {
369 this.use = use;
370 }
371 /**
372 *
373 * @return XXX
374 */
375 public WSDDFaultFlow[] getFaultFlows()
376 {
377 WSDDFaultFlow[] t = new WSDDFaultFlow[faultFlows.size()];
378 faultFlows.toArray(t);
379 return t;
380 }
381
382 /**
383 * Obtain the list of namespaces registered for this service
384 * @return a Vector of namespaces (Strings) which should dispatch to
385 * this service
386 */
387 public Vector getNamespaces()
388 {
389 return namespaces;
390 }
391
392 /**
393 *
394 * @param name XXX
395 * @return XXX
396 */
397 public WSDDFaultFlow getFaultFlow(QName name)
398 {
399 WSDDFaultFlow[] t = getFaultFlows();
400
401 for (int n = 0; n < t.length; n++) {
402 if (t[n].getQName().equals(name)) {
403 return t[n];
404 }
405 }
406
407 return null;
408 }
409
410 /**
411 *
412 * @param registry XXX
413 * @return XXX
414 * @throws ConfigurationException XXX
415 */
416 public Handler makeNewInstance(EngineConfiguration registry)
417 throws ConfigurationException
418 {
419 if (cachedService != null) {
420 return cachedService;
421 }
422
423 // Make sure tmr is initialized.
424 initTMR();
425
426 Handler reqHandler = null;
427 WSDDChain request = getRequestFlow();
428
429 if (request != null) {
430 reqHandler = request.getInstance(registry);
431 }
432
433 Handler providerHandler = null;
434
435 if (providerQName != null) {
436 try {
437 providerHandler = WSDDProvider.getInstance(providerQName,
438 this,
439 registry);
440 } catch (Exception e) {
441 throw new ConfigurationException(e);
442 }
443 if (providerHandler == null)
444 throw new WSDDException(
445 Messages.getMessage("couldntConstructProvider00"));
446 }
447
448 Handler respHandler = null;
449 WSDDChain response = getResponseFlow();
450
451 if (response != null) {
452 respHandler = response.getInstance(registry);
453 }
454
455 SOAPService service = new SOAPService(reqHandler, providerHandler,
456 respHandler);
457 service.setStyle(style);
458 service.setUse(use);
459 service.setServiceDescription(desc);
460
461 service.setHighFidelityRecording(!streaming);
462 service.setSendType(sendType);
463
464 if ( getQName() != null )
465 service.setName(getQName().getLocalPart());
466 service.setOptions(getParametersTable());
467
468 service.setRoles(roles);
469
470 service.setEngine(((WSDDDeployment)registry).getEngine());
471
472 if (use != Use.ENCODED) {
473 // If not encoded, turn off multi-refs and prefer
474 // not to sent xsi:type and xsi:nil
475 service.setOption(AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
476 service.setOption(AxisEngine.PROP_SEND_XSI, Boolean.FALSE);
477 }
478
479 // Set handlerInfoChain
480 if (_wsddHIchain != null) {
481 HandlerInfoChainFactory hiChainFactory = _wsddHIchain.getHandlerChainFactory();
482
483 service.setOption(Constants.ATTR_HANDLERINFOCHAIN, hiChainFactory);
484 }
485
486 AxisEngine.normaliseOptions(service);
487
488 WSDDFaultFlow [] faultFlows = getFaultFlows();
489 if (faultFlows != null && faultFlows.length > 0) {
490 FaultableHandler wrapper = new FaultableHandler(service);
491 for (int i = 0; i < faultFlows.length; i++) {
492 WSDDFaultFlow flow = faultFlows[i];
493 Handler faultHandler = flow.getInstance(registry);
494 wrapper.setOption("fault-" + flow.getQName().getLocalPart(),
495 faultHandler);
496 }
497 }
498
499 try {
500 service.getInitializedServiceDesc(MessageContext.getCurrentContext());
501 } catch (AxisFault axisFault) {
502 throw new ConfigurationException(axisFault);
503 }
504
505 cachedService = service;
506 return service;
507 }
508
509 public void deployTypeMapping(WSDDTypeMapping mapping)
510 throws WSDDException
511 {
512 if (!typeMappings.contains(mapping)) {
513 typeMappings.add(mapping);
514 }
515 if (tmr == null) {
516 createTMR();
517 }
518 try {
519 // Get the encoding style from the mapping, if it isn't set
520 // use the use of the service to map doc/lit or rpc/enc
521 String encodingStyle = mapping.getEncodingStyle();
522 if (encodingStyle == null) {
523 encodingStyle = use.getEncoding();
524 }
525 TypeMapping tm = tmr.getOrMakeTypeMapping(encodingStyle);
526 desc.setTypeMappingRegistry(tmr);
527 desc.setTypeMapping(tm);
528
529 SerializerFactory ser = null;
530 DeserializerFactory deser = null;
531
532 // Try to construct a serializerFactory by introspecting for the
533 // following:
534 // public static create(Class javaType, QName xmlType)
535 // public <constructor>(Class javaType, QName xmlType)
536 // public <constructor>()
537 //
538 // The BaseSerializerFactory createFactory() method is a utility
539 // that does this for us.
540 if (mapping.getSerializerName() != null &&
541 !mapping.getSerializerName().equals("")) {
542 ser = BaseSerializerFactory.createFactory(mapping.getSerializer(),
543 mapping.getLanguageSpecificType(),
544 mapping.getQName());
545 }
546 if (mapping instanceof WSDDArrayMapping && ser instanceof ArraySerializerFactory) {
547 WSDDArrayMapping am = (WSDDArrayMapping) mapping;
548 ArraySerializerFactory factory = (ArraySerializerFactory) ser;
549 factory.setComponentType(am.getInnerType());
550 }
551
552 if (mapping.getDeserializerName() != null &&
553 !mapping.getDeserializerName().equals("")) {
554 deser = BaseDeserializerFactory.createFactory(mapping.getDeserializer(),
555 mapping.getLanguageSpecificType(),
556 mapping.getQName());
557 }
558 tm.register( mapping.getLanguageSpecificType(), mapping.getQName(), ser, deser);
559 } catch (ClassNotFoundException e) {
560 log.error(Messages.getMessage("unabletoDeployTypemapping00", mapping.getQName().toString()), e);
561 throw new WSDDNonFatalException(e);
562 } catch (Exception e) {
563 throw new WSDDException(e);
564 }
565 }
566
567 /**
568 * Write this element out to a SerializationContext
569 */
570 public void writeToContext(SerializationContext context)
571 throws IOException {
572 AttributesImpl attrs = new AttributesImpl();
573 QName name = getQName();
574 if (name != null) {
575 attrs.addAttribute("", ATTR_NAME, ATTR_NAME,
576 "CDATA", context.qName2String(name));
577 }
578 if (providerQName != null) {
579 attrs.addAttribute("", ATTR_PROVIDER, ATTR_PROVIDER,
580 "CDATA", context.qName2String(providerQName));
581 }
582 if (style != Style.DEFAULT) {
583 attrs.addAttribute("", ATTR_STYLE, ATTR_STYLE,
584 "CDATA", style.getName());
585 }
586
587 if (use != Use.DEFAULT) {
588 attrs.addAttribute("", ATTR_USE, ATTR_USE,
589 "CDATA", use.getName());
590 }
591
592 if (streaming) {
593 attrs.addAttribute("", ATTR_STREAMING, ATTR_STREAMING,
594 "CDATA", "on");
595 }
596
597 if (sendType != Attachments.SEND_TYPE_NOTSET) {
598 attrs.addAttribute("", ATTR_ATTACHMENT_FORMAT,
599 ATTR_ATTACHMENT_FORMAT, "CDATA",
600 AttachmentsImpl.getSendTypeString(sendType));
601 }
602 context.startElement(WSDDConstants.QNAME_SERVICE, attrs);
603
604 if (desc.getWSDLFile() != null) {
605 context.startElement(QNAME_WSDLFILE, null);
606 context.writeSafeString(desc.getWSDLFile());
607 context.endElement();
608 }
609
610 if (desc.getDocumentation() != null) {
611 WSDDDocumentation documentation = new WSDDDocumentation(desc.getDocumentation());
612 documentation.writeToContext(context);
613 }
614
615 for (int i = 0; i < operations.size(); i++) {
616 WSDDOperation operation = (WSDDOperation) operations.elementAt(i);
617 operation.writeToContext(context);
618 }
619 writeFlowsToContext(context);
620 writeParamsToContext(context);
621
622
623 for (int i=0; i < typeMappings.size(); i++) {
624 ((WSDDTypeMapping) typeMappings.elementAt(i)).writeToContext(context);
625 }
626
627 for (int i=0; i < namespaces.size(); i++ ) {
628 context.startElement(QNAME_NAMESPACE, null);
629 context.writeString((String)namespaces.get(i));
630 context.endElement();
631 }
632
633 String endpointURL = desc.getEndpointURL();
634 if (endpointURL != null) {
635 context.startElement(QNAME_ENDPOINTURL, null);
636 context.writeSafeString(endpointURL);
637 context.endElement();
638 }
639
640 if (_wsddHIchain != null) {
641 _wsddHIchain.writeToContext(context);
642
643 }
644
645 context.endElement();
646
647
648 }
649
650 public void setCachedService(SOAPService service)
651 {
652 cachedService = service;
653 }
654
655 public Vector getTypeMappings() {
656 return typeMappings;
657 }
658
659 public void setTypeMappings(Vector typeMappings) {
660 this.typeMappings = typeMappings;
661 }
662
663 public void deployToRegistry(WSDDDeployment registry)
664 {
665 registry.addService(this);
666
667 // Register the name of the service as a valid namespace, just for
668 // backwards compatibility
669 registry.registerNamespaceForService(getQName().getLocalPart(), this);
670
671 for (int i = 0; i < namespaces.size(); i++) {
672 String namespace = (String) namespaces.elementAt(i);
673 registry.registerNamespaceForService(namespace, this);
674 }
675
676 super.deployToRegistry(registry);
677 }
678
679 public void removeNamespaceMappings(WSDDDeployment registry)
680 {
681 for (int i = 0; i < namespaces.size(); i++) {
682 String namespace = (String) namespaces.elementAt(i);
683 registry.removeNamespaceMapping(namespace);
684 }
685 registry.removeNamespaceMapping(getQName().getLocalPart());
686 }
687
688 public TypeMapping getTypeMapping(String encodingStyle) {
689 // If type mapping registry not initialized yet, return null.
690 if (tmr == null) {
691 return null;
692 }
693 return (TypeMapping) tmr.getOrMakeTypeMapping(encodingStyle);
694 }
695
696
697 public WSDDJAXRPCHandlerInfoChain getHandlerInfoChain() {
698 return _wsddHIchain;
699 }
700
701 public void setHandlerInfoChain(WSDDJAXRPCHandlerInfoChain hichain) {
702 _wsddHIchain = hichain;
703 }
704 }