blob: 372c50a99171cd8b95a28639a6ff6ad1d3b96768 [file] [log] [blame]
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.axis.deployment.wsdd;
import org.apache.axis.AxisEngine;
import org.apache.axis.AxisFault;
import org.apache.axis.ConfigurationException;
import org.apache.axis.Constants;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.FaultableHandler;
import org.apache.axis.Handler;
import org.apache.axis.MessageContext;
import org.apache.axis.attachments.Attachments;
import org.apache.axis.attachments.AttachmentsImpl;
import org.apache.axis.constants.Style;
import org.apache.axis.constants.Use;
import org.apache.axis.description.JavaServiceDesc;
import org.apache.axis.description.ServiceDesc;
import org.apache.axis.encoding.SerializationContext;
import org.apache.axis.encoding.TypeMapping;
import org.apache.axis.encoding.TypeMappingRegistry;
import org.apache.axis.encoding.TypeMappingRegistryImpl;
import org.apache.axis.handlers.HandlerInfoChainFactory;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.providers.java.JavaProvider;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.XMLUtils;
import org.w3c.dom.Element;
import org.xml.sax.helpers.AttributesImpl;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* A service represented in WSDD.
*
* @author Glen Daniels (gdaniels@apache.org)
*/
public class WSDDService
extends WSDDTargetedChain
implements WSDDTypeMappingContainer
{
private TypeMappingRegistry tmr = null;
private Vector faultFlows = new Vector();
private Vector typeMappings = new Vector();
private Vector operations = new Vector();
/** Which namespaces should auto-dispatch to this service? */
private Vector namespaces = new Vector();
/** Which roles does this service support? */
private List roles = new ArrayList();
private String descriptionURL;
/** Style - document, wrapped, message, or RPC (the default) */
private Style style = Style.DEFAULT;
/** Use - encoded (the default) or literal */
private Use use = Use.DEFAULT;
private transient SOAPService cachedService = null;
/**
* Our provider - used to figure out which Handler we use as a service
* pivot (see getInstance() below)
*/
private QName providerQName;
// private HandlerInfoChainFactory _hiChainFactory;
private WSDDJAXRPCHandlerInfoChain _wsddHIchain;
JavaServiceDesc desc = new JavaServiceDesc();
/**
* Is streaming (i.e. NO high-fidelity recording, deserialize on the fly)
* on for this service?
*/
private boolean streaming = false;
/**
* What attachment format should be used?
*/
private int sendType = Attachments.SEND_TYPE_NOTSET;
/**
* Default constructor
*/
public WSDDService()
{
}
/**
*
* @param e (Element) XXX
* @throws WSDDException XXX
*/
public WSDDService(Element e)
throws WSDDException
{
super(e);
desc.setName(getQName().getLocalPart());
String styleStr = e.getAttribute(ATTR_STYLE);
if (styleStr != null && !styleStr.equals("")) {
style = Style.getStyle(styleStr, Style.DEFAULT);
desc.setStyle(style);
providerQName = style.getProvider();
}
String useStr = e.getAttribute(ATTR_USE);
if (useStr != null && !useStr.equals("")) {
use = Use.getUse(useStr, Use.DEFAULT);
desc.setUse(use);
} else {
if (style != Style.RPC) {
// Default to use=literal if not style=RPC
use = Use.LITERAL;
desc.setUse(use);
}
}
String streamStr = e.getAttribute(ATTR_STREAMING);
if (streamStr != null && streamStr.equals("on")) {
streaming = true;
}
String attachmentStr = e.getAttribute(ATTR_ATTACHMENT_FORMAT);
if (attachmentStr != null && !attachmentStr.equals("")) {
sendType = AttachmentsImpl.getSendType(attachmentStr);
}
Element [] operationElements = getChildElements(e, ELEM_WSDD_OPERATION);
for (int i = 0; i < operationElements.length; i++) {
WSDDOperation operation = new WSDDOperation(operationElements[i],
desc);
addOperation(operation);
}
Element [] typeMappingElements = getChildElements(e, ELEM_WSDD_TYPEMAPPING);
for (int i = 0; i < typeMappingElements.length; i++) {
WSDDTypeMapping mapping =
new WSDDTypeMapping(typeMappingElements[i]);
typeMappings.add(mapping);
}
Element [] beanMappingElements = getChildElements(e, ELEM_WSDD_BEANMAPPING);
for (int i = 0; i < beanMappingElements.length; i++) {
WSDDBeanMapping mapping =
new WSDDBeanMapping(beanMappingElements[i]);
typeMappings.add(mapping);
}
Element [] arrayMappingElements = getChildElements(e, ELEM_WSDD_ARRAYMAPPING);
for (int i = 0; i < arrayMappingElements.length; i++) {
WSDDArrayMapping mapping =
new WSDDArrayMapping(arrayMappingElements[i]);
typeMappings.add(mapping);
}
Element [] namespaceElements = getChildElements(e, ELEM_WSDD_NAMESPACE);
for (int i = 0; i < namespaceElements.length; i++) {
// Register a namespace for this service
String ns = XMLUtils.getChildCharacterData(namespaceElements[i]);
namespaces.add(ns);
}
if (!namespaces.isEmpty())
desc.setNamespaceMappings(namespaces);
Element [] roleElements = getChildElements(e, ELEM_WSDD_ROLE);
for (int i = 0; i < roleElements.length; i++) {
String role = XMLUtils.getChildCharacterData(roleElements[i]);
roles.add(role);
}
Element wsdlElem = getChildElement(e, ELEM_WSDD_WSDLFILE);
if (wsdlElem != null) {
String fileName = XMLUtils.getChildCharacterData(wsdlElem);
desc.setWSDLFile(fileName.trim());
}
Element docElem = getChildElement(e, ELEM_WSDD_DOC);
if (docElem != null) {
WSDDDocumentation documentation = new WSDDDocumentation(docElem);
desc.setDocumentation(documentation.getValue());
}
Element urlElem = getChildElement(e, ELEM_WSDD_ENDPOINTURL);
if (urlElem != null) {
String endpointURL = XMLUtils.getChildCharacterData(urlElem);
desc.setEndpointURL(endpointURL);
}
String providerStr = e.getAttribute(ATTR_PROVIDER);
if (providerStr != null && !providerStr.equals("")) {
providerQName = XMLUtils.getQNameFromString(providerStr, e);
if (WSDDConstants.QNAME_JAVAMSG_PROVIDER.equals(providerQName)) {
// Message style if message provider...
desc.setStyle(Style.MESSAGE);
}
}
// Add in JAX-RPC support for HandlerInfo chains
Element hcEl = getChildElement(e, ELEM_WSDD_JAXRPC_CHAIN);
if (hcEl != null) {
_wsddHIchain = new WSDDJAXRPCHandlerInfoChain(hcEl);
}
// Initialize TypeMappingRegistry
initTMR();
// call to validate standard descriptors for this service
validateDescriptors();
}
/**
* Initialize a TypeMappingRegistry with the
* WSDDTypeMappings.
* Note: Extensions of WSDDService may override
* initTMR to popluate the tmr with different
* type mappings.
*/
protected void initTMR() throws WSDDException
{
// If not created, construct a tmr
// and populate it with the type mappings.
if (tmr == null) {
createTMR();
for (int i=0; i<typeMappings.size(); i++) {
deployTypeMapping((WSDDTypeMapping)
typeMappings.get(i));
}
}
}
private void createTMR() {
tmr = new TypeMappingRegistryImpl(false);
String version = getParameter("typeMappingVersion");
((TypeMappingRegistryImpl)tmr).doRegisterFromVersion(version);
}
/**
* This method can be used for dynamic deployment using new WSDDService()
* etc. It validates some standard parameters for some standard providers
* (if present). Do this before deployment.deployService().
*/
public void validateDescriptors() throws WSDDException
{
if (tmr == null) {
initTMR();
}
desc.setTypeMappingRegistry(tmr);
desc.setTypeMapping(getTypeMapping(desc.getUse().getEncoding()));
String allowedMethods = getParameter(JavaProvider.OPTION_ALLOWEDMETHODS);
if (allowedMethods != null && !"*".equals(allowedMethods)) {
ArrayList methodList = new ArrayList();
StringTokenizer tokenizer = new StringTokenizer(allowedMethods, " ,");
while (tokenizer.hasMoreTokens()) {
methodList.add(tokenizer.nextToken());
}
desc.setAllowedMethods(methodList);
}
}
/**
* Add a WSDDTypeMapping to the Service.
* @param mapping
**/
public void addTypeMapping(WSDDTypeMapping mapping) {
typeMappings.add(mapping);
}
/**
* Add a WSDDOperation to the Service.
* @param operation the operation to add
**/
public void addOperation(WSDDOperation operation) {
operations.add(operation);
desc.addOperationDesc(operation.getOperationDesc());
}
protected QName getElementName()
{
return QNAME_SERVICE;
}
/**
* Get any service description URL which might be associated with this
* service.
*
* @return a String containing a URL, or null.
*/
public String getServiceDescriptionURL()
{
return descriptionURL;
}
/**
* Set the service description URL for this service.
*
* @param sdUrl a String containing a URL
*/
public void setServiceDescriptionURL(String sdUrl)
{
descriptionURL = sdUrl;
}
public QName getProviderQName() {
return providerQName;
}
public void setProviderQName(QName providerQName) {
this.providerQName = providerQName;
}
public ServiceDesc getServiceDesc() {
return desc;
}
/**
* Get the service style - document or RPC
*/
public Style getStyle() {
return style;
}
/**
* Set the service style - document or RPC
*/
public void setStyle(Style style) {
this.style = style;
}
/**
* Get the service use - literal or encoded
*/
public Use getUse() {
return use;
}
/**
* Set the service use - literal or encoded
*/
public void setUse(Use use) {
this.use = use;
}
/**
*
* @return XXX
*/
public WSDDFaultFlow[] getFaultFlows()
{
WSDDFaultFlow[] t = new WSDDFaultFlow[faultFlows.size()];
faultFlows.toArray(t);
return t;
}
/**
* Obtain the list of namespaces registered for this service
* @return a Vector of namespaces (Strings) which should dispatch to
* this service
*/
public Vector getNamespaces()
{
return namespaces;
}
/**
*
* @param name XXX
* @return XXX
*/
public WSDDFaultFlow getFaultFlow(QName name)
{
WSDDFaultFlow[] t = getFaultFlows();
for (int n = 0; n < t.length; n++) {
if (t[n].getQName().equals(name)) {
return t[n];
}
}
return null;
}
/**
*
* @param registry XXX
* @return XXX
* @throws ConfigurationException XXX
*/
public Handler makeNewInstance(EngineConfiguration registry)
throws ConfigurationException
{
if (cachedService != null) {
return cachedService;
}
// Make sure tmr is initialized.
initTMR();
Handler reqHandler = null;
WSDDChain request = getRequestFlow();
if (request != null) {
reqHandler = request.getInstance(registry);
}
Handler providerHandler = null;
if (providerQName != null) {
try {
providerHandler = WSDDProvider.getInstance(providerQName,
this,
registry);
} catch (Exception e) {
throw new ConfigurationException(e);
}
if (providerHandler == null)
throw new WSDDException(
Messages.getMessage("couldntConstructProvider00"));
}
Handler respHandler = null;
WSDDChain response = getResponseFlow();
if (response != null) {
respHandler = response.getInstance(registry);
}
SOAPService service = new SOAPService(reqHandler, providerHandler,
respHandler);
service.setStyle(style);
service.setUse(use);
service.setServiceDescription(desc);
service.setHighFidelityRecording(!streaming);
service.setSendType(sendType);
if ( getQName() != null )
service.setName(getQName().getLocalPart());
service.setOptions(getParametersTable());
service.setRoles(roles);
service.setEngine(((WSDDDeployment)registry).getEngine());
if (use != Use.ENCODED) {
// If not encoded, turn off multi-refs and prefer
// not to sent xsi:type and xsi:nil
service.setOption(AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
service.setOption(AxisEngine.PROP_SEND_XSI, Boolean.FALSE);
}
// Set handlerInfoChain
if (_wsddHIchain != null) {
HandlerInfoChainFactory hiChainFactory = _wsddHIchain.getHandlerChainFactory();
service.setOption(Constants.ATTR_HANDLERINFOCHAIN, hiChainFactory);
}
AxisEngine.normaliseOptions(service);
WSDDFaultFlow [] faultFlows = getFaultFlows();
if (faultFlows != null && faultFlows.length > 0) {
FaultableHandler wrapper = new FaultableHandler(service);
for (int i = 0; i < faultFlows.length; i++) {
WSDDFaultFlow flow = faultFlows[i];
Handler faultHandler = flow.getInstance(registry);
wrapper.setOption("fault-" + flow.getQName().getLocalPart(),
faultHandler);
}
}
try {
service.getInitializedServiceDesc(MessageContext.getCurrentContext());
} catch (AxisFault axisFault) {
throw new ConfigurationException(axisFault);
}
cachedService = service;
return service;
}
public void deployTypeMapping(WSDDTypeMapping mapping)
throws WSDDException
{
if (!typeMappings.contains(mapping)) {
typeMappings.add(mapping);
}
if (tmr == null) {
createTMR();
}
// Get the encoding style from the mapping, if it isn't set
// use the use of the service to map doc/lit or rpc/enc
String encodingStyle = mapping.getEncodingStyle();
if (encodingStyle == null) {
encodingStyle = use.getEncoding();
}
TypeMapping tm = tmr.getOrMakeTypeMapping(encodingStyle);
desc.setTypeMappingRegistry(tmr);
desc.setTypeMapping(tm);
mapping.registerTo(tm);
}
/**
* Write this element out to a SerializationContext
*/
public void writeToContext(SerializationContext context)
throws IOException {
AttributesImpl attrs = new AttributesImpl();
QName name = getQName();
if (name != null) {
attrs.addAttribute("", ATTR_NAME, ATTR_NAME,
"CDATA", context.qName2String(name));
}
if (providerQName != null) {
attrs.addAttribute("", ATTR_PROVIDER, ATTR_PROVIDER,
"CDATA", context.qName2String(providerQName));
}
if (style != Style.DEFAULT) {
attrs.addAttribute("", ATTR_STYLE, ATTR_STYLE,
"CDATA", style.getName());
}
if (use != Use.DEFAULT) {
attrs.addAttribute("", ATTR_USE, ATTR_USE,
"CDATA", use.getName());
}
if (streaming) {
attrs.addAttribute("", ATTR_STREAMING, ATTR_STREAMING,
"CDATA", "on");
}
if (sendType != Attachments.SEND_TYPE_NOTSET) {
attrs.addAttribute("", ATTR_ATTACHMENT_FORMAT,
ATTR_ATTACHMENT_FORMAT, "CDATA",
AttachmentsImpl.getSendTypeString(sendType));
}
context.startElement(WSDDConstants.QNAME_SERVICE, attrs);
if (desc.getWSDLFile() != null) {
context.startElement(QNAME_WSDLFILE, null);
context.writeSafeString(desc.getWSDLFile());
context.endElement();
}
if (desc.getDocumentation() != null) {
WSDDDocumentation documentation = new WSDDDocumentation(desc.getDocumentation());
documentation.writeToContext(context);
}
for (int i = 0; i < operations.size(); i++) {
WSDDOperation operation = (WSDDOperation) operations.elementAt(i);
operation.writeToContext(context);
}
writeFlowsToContext(context);
writeParamsToContext(context);
for (int i=0; i < typeMappings.size(); i++) {
((WSDDTypeMapping) typeMappings.elementAt(i)).writeToContext(context);
}
for (int i=0; i < namespaces.size(); i++ ) {
context.startElement(QNAME_NAMESPACE, null);
context.writeString((String)namespaces.get(i));
context.endElement();
}
String endpointURL = desc.getEndpointURL();
if (endpointURL != null) {
context.startElement(QNAME_ENDPOINTURL, null);
context.writeSafeString(endpointURL);
context.endElement();
}
if (_wsddHIchain != null) {
_wsddHIchain.writeToContext(context);
}
context.endElement();
}
public void setCachedService(SOAPService service)
{
cachedService = service;
}
public Vector getTypeMappings() {
return typeMappings;
}
public void setTypeMappings(Vector typeMappings) {
this.typeMappings = typeMappings;
}
public void deployToRegistry(WSDDDeployment registry)
{
registry.addService(this);
// Register the name of the service as a valid namespace, just for
// backwards compatibility
registry.registerNamespaceForService(getQName().getLocalPart(), this);
for (int i = 0; i < namespaces.size(); i++) {
String namespace = (String) namespaces.elementAt(i);
registry.registerNamespaceForService(namespace, this);
}
super.deployToRegistry(registry);
}
public void removeNamespaceMappings(WSDDDeployment registry)
{
for (int i = 0; i < namespaces.size(); i++) {
String namespace = (String) namespaces.elementAt(i);
registry.removeNamespaceMapping(namespace);
}
registry.removeNamespaceMapping(getQName().getLocalPart());
}
public TypeMapping getTypeMapping(String encodingStyle) {
// If type mapping registry not initialized yet, return null.
if (tmr == null) {
return null;
}
return (TypeMapping) tmr.getOrMakeTypeMapping(encodingStyle);
}
public WSDDJAXRPCHandlerInfoChain getHandlerInfoChain() {
return _wsddHIchain;
}
public void setHandlerInfoChain(WSDDJAXRPCHandlerInfoChain hichain) {
_wsddHIchain = hichain;
}
}