/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.utilities;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Utility for combining WSDL and XSD into a single file, with a specific
* service endpoint.
*
* @author Chris Wilper
*/
public class RuntimeWSDL {
/** The final WSDL document. */
private Document _wsdlDoc;
/**
* Instantiate from the given files and service endpoint URL.
*/
public RuntimeWSDL(File schemaFile, File sourceWSDL, String endpoint)
throws IOException {
try {
// init dom parser and parse input
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document xsdDoc = builder.parse(schemaFile);
_wsdlDoc = builder.parse(sourceWSDL);
// put schema into the wsdl types section
Element typesElement = getTopElement("types");
removeChildren(typesElement);
Node xsdNode =
_wsdlDoc.importNode(xsdDoc.getDocumentElement(), true); // deep copy
typesElement.appendChild(xsdNode);
// set the endpoint
// - requires an existing service element with a name attribute
// - requires at least one port element under the service element
// - removes extra ports if more than one exist under service
// - sets the port name to service[@name] plus "-$scheme-Port",
// where $scheme the uppercase URI scheme of the endpoint
// - sets the address location to given endpoint URL
Element serviceElement = getTopElement("service");
String serviceName = serviceElement.getAttributeNS(null, "name");
if (serviceName == null) {
throw new IOException("WSDL missing required attribute of "
+ "service element: name");
}
NodeList ports = serviceElement.getElementsByTagNameNS("*", "port");
while (ports.getLength() > 1) {
serviceElement.removeChild(ports.item(0));
}
if (ports.getLength() == 0) {
throw new IOException("WSDL missing required element: port");
}
Element port = (Element) ports.item(0);
int i = endpoint.indexOf(":");
String schemePart = "";
if (i != -1) {
schemePart = "-" + endpoint.substring(0, i).toUpperCase();
}
port.setAttribute("name", serviceName + schemePart + "-Port");
Element address =
(Element) port.getElementsByTagNameNS("*", "address")
.item(0);
if (address != null) {
address.setAttribute("location", endpoint);
} else {
throw new IOException("WSDL missing required element: address");
}
} catch (Exception e) {
if (e instanceof IOException) {
throw (IOException) e;
} else {
IOException ioe = new IOException("Error getting RuntimeWSDL");
ioe.initCause(e);
throw ioe;
}
}
}
private Element getTopElement(String name) throws IOException {
Element element =
(Element) _wsdlDoc.getDocumentElement()
.getElementsByTagNameNS("*", name).item(0);
if (element != null) {
return element;
} else {
throw new IOException("WSDL missing required element: " + name);
}
}
private static final void removeChildren(Element element) {
Node firstChild = element.getFirstChild();
while (firstChild != null) {
element.removeChild(firstChild);
firstChild = element.getFirstChild();
}
}
/**
* Serialize the final WSDL document to the given writer.
*/
public void serialize(Writer out) throws IOException {
OutputFormat fmt = new OutputFormat("XML", "UTF-8", true);
fmt.setIndent(2);
fmt.setLineWidth(80);
fmt.setPreserveSpace(false);
fmt.setOmitXMLDeclaration(false);
fmt.setOmitDocumentType(true);
XMLSerializer ser = new XMLSerializer(out, fmt);
ser.serialize(_wsdlDoc);
}
/**
* Command-line test. Usage: java RuntimeWSDL schemaFile sourceWSDL endpoint
*/
public static void main(String[] args) throws Exception {
java.io.PrintWriter out = new java.io.PrintWriter(System.out);
new RuntimeWSDL(new File(args[0]), new File(args[1]), args[2])
.serialize(out);
out.flush();
}
}