/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.tuscany.binding.celtix;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.xml.sax.InputSource;
import static org.osoa.sca.Version.XML_NAMESPACE_1_0;
import org.osoa.sca.annotations.Constructor;
import org.osoa.sca.annotations.Scope;
import org.apache.tuscany.spi.annotation.Autowire;
import org.apache.tuscany.spi.component.CompositeComponent;
import org.apache.tuscany.spi.deployer.DeploymentContext;
import org.apache.tuscany.spi.extension.LoaderExtension;
import org.apache.tuscany.spi.loader.LoaderException;
import org.apache.tuscany.spi.model.ModelObject;
import org.apache.tuscany.spi.loader.LoaderRegistry;
import org.apache.tuscany.idl.wsdl.WSDLDefinitionRegistry;
import org.apache.tuscany.idl.wsdl.WSDLDefinitionRegistryImpl;
import org.apache.tuscany.idl.wsdl.WSDLDefinitionRegistryImpl.Monitor;
/**
* Parses a WebServiceBindingDefinition
entry in an assembly XML file
*
* @version $Rev$ $Date$
*/
@Scope("COMPOSITE")
public class WebServiceBindingLoader extends LoaderExtension {
public static final QName BINDING_WS = new QName(XML_NAMESPACE_1_0, "binding.ws");
protected WSDLDefinitionRegistry wsdlRegistry;
@Constructor({"registry"})
public WebServiceBindingLoader(@Autowire LoaderRegistry registry) {
super(registry);
//FIXME: this is a hack, WSDLDefinitionRegistry should not be created here
if (wsdlRegistry == null) {
try {
wsdlRegistry = new WSDLDefinitionRegistryImpl();
Monitor monitor = new Monitor() {
public void readingWSDL(String namespace, URL location) {
}
public void cachingDefinition(String namespace, URL location) {
}
};
((WSDLDefinitionRegistryImpl) wsdlRegistry).setMonitor(monitor);
} catch (javax.wsdl.WSDLException e) {
//do nothing
}
}
}
public QName getXMLType() {
return BINDING_WS;
}
public WebServiceBindingDefinition load(CompositeComponent parent,
ModelObject object,
XMLStreamReader reader,
DeploymentContext deploymentContext)
throws XMLStreamException, LoaderException {
// not sure what uri was here ? String uri = reader.getAttributeValue(null, "uri");
String uri = null;
String endpointAttribute = reader.getAttributeValue(null, "endpoint");
//String portURI = reader.getAttributeValue(null, "port");
String wsdlLocation = reader.getAttributeValue(null, "location");
try {
return createBinding(uri, endpointAttribute, wsdlLocation, deploymentContext);
} catch (Exception e) {
throw new LoaderException(e);
}
}
private WebServiceBindingDefinition createBinding(String port, String portURI, String wsdlLocation,
DeploymentContext deploymentContext)
throws WSDLException, IOException {
List definitions = null;
// FIXME wsdlRegistry.getDefinitionsForNamespace(portNamespace,
// resourceLoader);
// Get the WSDL port namespace and name
if (port == null && portURI != null) {
int h = portURI.indexOf('#');
String portNamespace = portURI.substring(0, h);
String serviceName;
String portName;
String fragment = portURI.substring(h + 1);
if (fragment.startsWith("wsdl.endpoint(") && fragment.endsWith(")")) {
fragment = fragment.substring(14, fragment.length() - 1);
int slash = fragment.indexOf('/');
if (slash != -1) {
serviceName = fragment.substring(0, slash);
portName = fragment.substring(slash + 1);
} else {
serviceName = null;
portName = fragment;
}
} else {
serviceName = null;
portName = fragment;
}
// FIXME need to find out how to get wsdl and what context to use --- terrible hack attack!
// URL wsdlurl = Thread.currentThread().getContextClassLoader().getResource(wsdlLocation);
if (null == wsdlLocation) {
throw new RuntimeException("Failed to determin wsdl location on binding. "
+ "Try specifying 'location' attribute on binding.");
}
URL wsdlurl = deploymentContext.getClassLoader().getResource(wsdlLocation);
if (wsdlurl == null) {
throw new RuntimeException("Failed to load wsdl from '" + wsdlLocation + "'");
}
WSDLFactory factory = WSDLFactory.newInstance();
WSDLReader reader = factory.newWSDLReader();
reader.setFeature("javax.wsdl.verbose", false);
InputSource input = new InputSource(wsdlurl.openStream());
Definition wsdlDef = reader.readWSDL(wsdlurl.toString(), input);
definitions = new LinkedList();
definitions.add(wsdlDef);
// FIXME all the above needs to better addressed.
//FIXME: if a global wsdl cached is used, we need to do a registration here
String namespace = wsdlDef.getTargetNamespace();
wsdlRegistry.loadDefinition(namespace, wsdlurl);
Definition definition = null;
Port thePort = null;
Service service = null;
for (Definition def : definitions) {
// Find the port with the given name
for (Service serv : (Collection) def.getServices().values()) {
QName sqn = serv.getQName();
if (serviceName != null
&& !serviceName.equals(sqn.getLocalPart())) {
continue;
}
Port p = serv.getPort(portName);
if (p != null) {
service = serv;
definition = def;
thePort = p;
break;
}
}
}
if (thePort == null) {
throw new IllegalArgumentException("Cannot find WSDL port " + portURI);
}
WebServiceBindingDefinition wsBinding = new WebServiceBindingDefinition(definition, thePort, port, portURI, service);
wsBinding.setWSDLDefinitionRegistry(wsdlRegistry);
return wsBinding;
}
// FIXME - return a broken binding for now
return new WebServiceBindingDefinition(null, null, null, portURI, null);
}
}