/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
* Free SoftwareFoundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.soap.wsdl;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.namespace.QName;
import static com.caucho.soap.wsdl.WSDLConstants.*;
import com.caucho.java.JavaWriter;
import com.caucho.util.L10N;
import com.caucho.vfs.Vfs;
import com.caucho.vfs.WriteStream;
import com.caucho.xml.schema.Type;
/**
* WSDL Definitions top level
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="definitions", namespace=WSDL_NAMESPACE)
public class WSDLDefinitions extends WSDLExtensibleDocumented {
@XmlTransient
private static final L10N L = new L10N(WSDLDefinitions.class);
@XmlAttribute(name="name")
private String _name;
@XmlAttribute(name="targetNamespace")
private String _targetNamespace;
@XmlElement(name="import", namespace=WSDL_NAMESPACE)
private List<WSDLImport> _imports;
@XmlElement(name="types", namespace=WSDL_NAMESPACE, required=true)
private List<WSDLTypes> _types;
@XmlElement(name="message", namespace=WSDL_NAMESPACE, required=true)
private List<WSDLMessage> _messages;
@XmlElement(name="portType", namespace=WSDL_NAMESPACE, required=true)
private List<WSDLPortType> _portTypes;
@XmlElement(name="binding", namespace=WSDL_NAMESPACE, required=true)
private List<WSDLBinding> _bindings;
@XmlElement(name="service", namespace=WSDL_NAMESPACE, required=true)
private List<WSDLService> _services;
@XmlTransient
private final Map<QName,WSDLMessage> _messageMap
= new HashMap<QName,WSDLMessage>();
@XmlTransient
private final Map<QName,WSDLPortType> _portTypeMap
= new HashMap<QName,WSDLPortType>();
@XmlTransient
private final Map<QName,WSDLBinding> _bindingMap
= new HashMap<QName,WSDLBinding>();
@XmlTransient
private String _endpointAddress;
@XmlTransient
private String _bindingId;
/**
* Sets the definition name.
*/
public void setName(String name)
{
_name = name;
}
public String getName()
{
return _name;
}
/**
* Sets the target namespace
*/
public void setTargetNamespace(String uri)
{
_targetNamespace = uri;
}
/**
* Gets the target namespace
*/
public String getTargetNamespace()
{
return _targetNamespace;
}
public List<WSDLImport> getImports()
{
if (_imports == null)
return _imports = new ArrayList<WSDLImport>();
return _imports;
}
public List<WSDLTypes> getTypes()
{
if (_types == null)
return _types = new ArrayList<WSDLTypes>();
return _types;
}
public List<WSDLMessage> getMessages()
{
if (_messages == null)
return _messages = new ArrayList<WSDLMessage>();
return _messages;
}
public List<WSDLPortType> getPortTypes()
{
if (_portTypes == null)
return _portTypes = new ArrayList<WSDLPortType>();
return _portTypes;
}
public List<WSDLBinding> getBindings()
{
if (_bindings == null)
return _bindings = new ArrayList<WSDLBinding>();
return _bindings;
}
public List<WSDLService> getServices()
{
if (_services == null)
return _services = new ArrayList<WSDLService>();
return _services;
}
public String getBindingId(QName serviceName, QName portName)
{
if (_bindingId == null) {
if (! serviceName.getNamespaceURI().equals(getTargetNamespace()))
return null;
// first find out which binding we're looking for
QName bindingName = null;
if (_services != null) {
for (int i = 0; i < _services.size(); i++) {
WSDLService service = _services.get(i);
if (serviceName.getLocalPart().equals(service.getName())) {
List<WSDLPort> ports = service.getPorts();
for (int j = 0; j < ports.size(); j++) {
WSDLPort port = ports.get(j);
if (portName.getLocalPart().equals(port.getName())) {
bindingName = port.getBinding();
break;
}
}
if (bindingName != null)
break;
}
}
}
if (bindingName != null && _bindings != null) {
for (int i = 0; i < _bindings.size(); i++) {
WSDLBinding binding = _bindings.get(i);
if (bindingName.getLocalPart().equals(binding.getName())) {
List<Object> any = binding.getAny();
for (int j = 0; j < any.size(); j++) {
if (any.get(j) instanceof SOAPBinding) {
SOAPBinding soapBinding = (SOAPBinding) any.get(j);
_bindingId = soapBinding.getTransport();
return _bindingId;
}
}
}
}
}
}
return _bindingId;
}
public String getEndpointAddress(QName serviceName, QName portName)
{
if (_endpointAddress == null) {
if (! serviceName.getNamespaceURI().equals(getTargetNamespace()))
return null;
// dig down to find the <soap:address location="..."/>
if (_services != null) {
for (int i = 0; i < _services.size(); i++) {
WSDLService service = _services.get(i);
if (serviceName.getLocalPart().equals(service.getName())) {
List<WSDLPort> ports = service.getPorts();
for (int j = 0; j < ports.size(); j++) {
WSDLPort port = ports.get(j);
if (portName.getLocalPart().equals(port.getName())) {
List<Object> any = port.getAny();
for (int k = 0; k < any.size(); k++) {
if (any.get(k) instanceof SOAPAddress) {
SOAPAddress address = (SOAPAddress) any.get(k);
_endpointAddress = address.getLocation();
return _endpointAddress;
}
}
}
}
}
}
}
}
return _endpointAddress;
}
/**
* Sets up the cached, transient data.
**/
public void afterUnmarshal(Unmarshaller u, Object o)
throws JAXBException, WSDLValidationException
{
if (_messages != null) {
for (WSDLMessage message : _messages) {
QName name = null;
if (_targetNamespace != null)
name = new QName(_targetNamespace, message.getName());
else
name = new QName(message.getName());
_messageMap.put(name, message);
}
}
if (_portTypes != null) {
for (WSDLPortType portType : _portTypes) {
QName name = null;
if (_targetNamespace != null)
name = new QName(_targetNamespace, portType.getName());
else
name = new QName(portType.getName());
_portTypeMap.put(name, portType);
}
}
if (_bindings != null) {
for (WSDLBinding binding : _bindings) {
QName name = null;
if (_targetNamespace != null)
name = new QName(_targetNamespace, binding.getName());
else
name = new QName(binding.getName());
_bindingMap.put(name, binding);
}
}
resolveImports(u);
for (WSDLMessage message : getMessages()) {
for (WSDLPart part : message.getParts()) {
Type type = getType(part.getElement());
if (type == null)
throw new WSDLValidationException(L.l("Element type {0} for part {1} of message {2} is not defined in this WSDL's schema", part.getElement(), part.getName(), message.getName()));
part.setType(type);
}
}
// check that all the messages referenced by operations are defined
for (WSDLPortType portType : getPortTypes()) {
portType.setDefinitions(this);
for (WSDLOperation operation : portType.getOperations()) {
operation.setPortType(portType);
for (WSDLOperationInput input : operation.getInputs()) {
WSDLMessage message = getMessage(input.getMessageName());
if (message == null)
throw new WSDLValidationException(L.l("Input message {0} for operation {1} is not defined in this WSDL", input.getMessageName(), operation.getName()));
input.setMessage(message);
}
for (WSDLOperationOutput output : operation.getOutputs()) {
WSDLMessage message = getMessage(output.getMessageName());
if (message == null)
throw new WSDLValidationException(L.l("Output message {0} for operation {1} is not defined in this WSDL", output.getMessageName(), operation.getName()));
output.setMessage(message);
}
for (WSDLOperationFault fault : operation.getFaults()) {
WSDLMessage message = getMessage(fault.getMessageName());
if (message == null)
throw new WSDLValidationException(L.l("Fault message {0} for operation {1} is not defined in this WSDL", fault.getMessageName(), operation.getName()));
fault.setMessage(message);
}
}
}
// assign the binding to a portType and check that all
// the operations are defined
for (WSDLBinding binding : getBindings()) {
WSDLPortType portType = getPortType(binding.getType());
if (portType == null)
throw new WSDLValidationException(L.l("PortType {0} for binding {1} is not defined in this WSDL", binding.getType(), binding.getName()));
binding.setPortType(portType);
for (WSDLBindingOperation bindingOp : binding.getOperations()) {
WSDLOperation operation = portType.getOperation(bindingOp.getName());
if (operation == null)
throw new WSDLValidationException(L.l("PortType {0} has no operation {1} for binding {2}", portType.getName(), bindingOp.getName(), binding.getName()));
bindingOp.setOperation(operation);
}
}
}
public WSDLMessage getMessage(QName name)
{
return _messageMap.get(name);
}
public WSDLPortType getPortType(QName name)
{
return _portTypeMap.get(name);
}
public WSDLBinding getBinding(QName name)
{
return _bindingMap.get(name);
}
public Type getType(QName typeName)
{
if (_types == null)
return null;
for (int i = 0; i < _types.size(); i++) {
WSDLTypes types = _types.get(i);
Type type = types.getType(typeName);
if (type != null)
return type;
}
return null;
}
public void resolveImports(Unmarshaller u)
throws JAXBException
{
if (_types == null)
return;
for (int i = 0; i < _types.size(); i++) {
WSDLTypes types = _types.get(i);
types.resolveImports(u);
}
}
public void writeJAXBClasses(File outputDirectory, String pkg)
throws IOException
{
if (_types == null)
return;
for (int i = 0; i < _types.size(); i++) {
WSDLTypes types = _types.get(i);
types.writeJAXBClasses(outputDirectory, pkg);
}
}
public void generateJava(Unmarshaller u,
File sourceDir, File classDir,
String pkg)
throws WSDLValidationException, JAXBException, IOException
{
for (WSDLService service : getServices()) {
for (WSDLPort port : service.getPorts()) {
WSDLBinding binding = getBinding(port.getBinding());
if (binding == null)
throw new WSDLValidationException(L.l("Binding {0} for port {1} not defined in this WSDL", port.getBinding(), port.getName()));
WSDLPortType portType = binding.getPortType();
File dir = new File(sourceDir, pkg.replace(".", File.separator));
dir.mkdirs();
File output = new File(dir, portType.getName() + ".java");
WriteStream os = null;
try {
os = Vfs.openWrite(output.toString());
JavaWriter out = new JavaWriter(os);
out.println("package " + pkg + ";");
out.println();
out.println("import java.math.BigDecimal;");
out.println("import java.math.BigInteger;");
out.println("import java.util.List;");
out.println("import javax.jws.WebMethod;");
out.println("import javax.jws.WebParam;");
out.println("import javax.jws.WebResult;");
out.println("import javax.jws.WebService;");
out.println("import javax.xml.datatype.XMLGregorianCalendar;");
out.println("import javax.xml.ws.RequestWrapper;");
out.println("import javax.xml.ws.ResponseWrapper;");
out.println();
out.print("@WebService(name=\"" + portType.getName() + "\",");
out.println("targetNamespace=\"" + getTargetNamespace() + "\")");
out.println("public interface " + portType.getName() + "{");
out.pushDepth();
for (WSDLBindingOperation bindingOp : binding.getOperations()) {
bindingOp.generateJava(out);
out.println();
out.println();
}
out.popDepth();
out.println("}");
}
finally {
if (os != null)
os.close();
}
output = new File(dir, portType.getName() + "Service.java");
os = null;
try {
os = Vfs.openWrite(output.toString());
JavaWriter out = new JavaWriter(os);
out.println("package " + pkg + ";");
out.println();
out.println("import java.net.URL;");
out.println("import javax.xml.namespace.QName;");
out.println("import javax.xml.ws.Service;");
out.println();
out.println("public class " + portType.getName() + "Service");
out.println(" extends Service");
out.println("{");
out.pushDepth();
out.print("public " + portType.getName() + "Service");
out.println("(URL wsdlDocumentLocation, QName serviceName)");
out.println("{");
out.pushDepth();
out.println("super(wsdlDocumentLocation, serviceName);");
out.popDepth();
out.println("}");
out.popDepth();
out.println("}");
}
finally {
if (os != null)
os.close();
}
}
}
writeJAXBClasses(sourceDir, pkg);
File dir = new File(sourceDir, pkg.replace(".", File.separator));
File[] sources = dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name)
{
return name.endsWith(".java");
}
});
if (sources.length == 0) {
// XXX Warning message?
System.out.println(" No sources found in " + dir + "!!!!!!");
return;
}
com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main();
String[] args = new String[2 + sources.length];
args[0] = "-d";
args[1] = classDir.getAbsolutePath();
for (int i = 0; i < sources.length; i++)
args[i + 2] = sources[i].getAbsolutePath();
javac.compile(args);
}
}