/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.wsdl;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.SimpleValue;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
//import com.eviware.soapui.SoapUI;
/**
* XML-Schema related tools
*
* @author Ole.Matzura
*/
public class SchemaUtils {
// private static final Logger log = Logger.getLogger( SchemaUtils.class );
public static SchemaTypeLoader loadSchemaTypes(String wsdlUrl) throws Exception {
// log.info( "Loading schema types from [" + wsdlUrl + "]");
SchemaTypeLoader schemaTypes = loadSchemaTypes(getSchemas(wsdlUrl));
return schemaTypes;
}
public static SchemaTypeLoader loadSchemaTypes(List schemas) throws Exception {
XmlOptions options = new XmlOptions();
options.setCompileNoValidation();
options.setCompileNoPvrRule();
options.setCompileDownloadUrls();
options.setCompileNoUpaRule();
ArrayList errorList = new ArrayList();
options.setErrorListener(errorList);
// schemas.add( XmlObject.Factory.parse( SoapUI.class.getResource("/soapEncoding.xsd") ));
try {
return XmlBeans.loadXsd((XmlObject[]) schemas.toArray(new XmlObject[schemas.size()]), options);
} catch (Exception e) {
for (int c = 0; c < errorList.size(); c++) {
System.out.println(errorList.get(c));
}
throw e;
}
}
public static List getSchemas(String wsdlUrl) throws Exception {
System.out.println("loading schema types from " + wsdlUrl);
XmlOptions options = new XmlOptions();
options.setCompileNoValidation();
options.setCompileDownloadUrls();
options.setCompileNoUpaRule();
options.setSaveUseOpenFrag();
options.setSaveSyntheticDocumentElement(new QName("http://www.w3.org/2001/XMLSchema", "schema"));
XmlObject xmlObject = XmlObject.Factory.parse(new URL(wsdlUrl), options);
XmlObject[] schemas = xmlObject.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:schema");
for (int i = 0; i < schemas.length; i++) {
XmlCursor xmlCursor = schemas[i].newCursor();
String xmlText = xmlCursor.getObject().xmlText(options);
schemas[i] = XmlObject.Factory.parse(xmlText, options);
schemas[i].documentProperties().setSourceName(wsdlUrl);
if (wsdlUrl.startsWith("file:")) {
;// fixRelativeFileImports( schemas[i] );
}
}
List result = new ArrayList(Arrays.asList(schemas));
XmlObject[] imports = xmlObject.selectPath("declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import");
for (int i = 0; i < imports.length; i++) {
String location = ((Element) imports[i].newDomNode()).getAttribute("location");
if (location != null) {
if (location.indexOf("://") > 0) {
result.addAll(getSchemas(location));
} else {
result.addAll(getSchemas(joinRelativeUrl(wsdlUrl, location)));
}
}
}
return result;
}
public static List getDefinitionUrls(String wsdlUrl) throws Exception {
List result = new ArrayList();
result.add(wsdlUrl);
XmlOptions options = new XmlOptions();
options.setCompileNoValidation();
options.setCompileDownloadUrls();
options.setCompileNoUpaRule();
options.setSaveUseOpenFrag();
options.setSaveSyntheticDocumentElement(new QName("http://www.w3.org/2001/XMLSchema", "schema"));
XmlObject xmlObject = XmlObject.Factory.parse(new URL(wsdlUrl), options);
XmlObject[] wsdlImports = xmlObject.selectPath("declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import");
for (int i = 0; i < wsdlImports.length; i++) {
String location = wsdlImports[i].newDomNode().getAttributes().getNamedItem("location").getNodeValue();
if (location != null) {
if (location.indexOf("://") > 0) {
result.addAll(getDefinitionUrls(location));
} else {
result.addAll(getDefinitionUrls(joinRelativeUrl(wsdlUrl, location)));
}
}
}
XmlObject[] schemaImports = xmlObject
.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import/@schemaLocation");
for (int i = 0; i < schemaImports.length; i++) {
String location = ((SimpleValue) schemaImports[i]).getStringValue();
if (location != null) {
if (location.indexOf("://") > 0) {
result.addAll(getDefinitionUrls(location));
} else {
result.addAll(getDefinitionUrls(joinRelativeUrl(wsdlUrl, location)));
}
}
}
XmlObject[] schemaIncludes = xmlObject
.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:include/@schemaLocation");
for (int i = 0; i < schemaIncludes.length; i++) {
String location = ((SimpleValue) schemaIncludes[i]).getStringValue();
if (location != null) {
if (location.indexOf("://") > 0) {
result.addAll(getDefinitionUrls(location));
} else {
result.addAll(getDefinitionUrls(joinRelativeUrl(wsdlUrl, location)));
}
}
}
return result;
}
public static String joinRelativeUrl(String root, String url) {
int ix = root.startsWith("file:") ? root.lastIndexOf(File.separatorChar) : root.lastIndexOf('/');
return root.substring(0, ix + 1) + url;
}
/**
* Fixes relative xsd imports in the specified schema. The schemaLocation of an xsd import must be an URI which is not the case if the
* loaded wsdl is loaded with the "file" schema (ie from the file system) and an import is relative.
*/
private static void fixRelativeFileImports(XmlObject xmlObject) throws Exception {
XmlObject[] imports = xmlObject.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import");
if (imports.length == 0) {
return;
}
String source = xmlObject.documentProperties().getSourceName();
int ix = source.lastIndexOf(File.separatorChar);
if (ix != -1) {
source = source.substring(0, ix + 1);
}
for (int c = 0; c < imports.length; c++) {
XmlObject importElement = imports[c];
System.out.println("XML IMPORT:" + importElement);
Node node = importElement.newDomNode();
System.out.println("node " + node);
NamedNodeMap map = node.getAttributes();
System.out.println("nodemap " + map);
Node locationNode = map.getNamedItem("schemaLocation");
System.out.println("locationNode: " + locationNode);
// Node locationNode = imports[c].newDomNode().getAttributes().getNamedItem( "schemaLocation" );
if (locationNode != null) {
String location = locationNode.getNodeValue();
if (location != null) {
URI uri = new URI(location);
if (!uri.isAbsolute()) {
locationNode.setNodeValue(source + location);
}
}
}
}
}
}