001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.tools.validator.internal;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.net.URI;
023: import java.util.ArrayList;
024: import java.util.HashMap;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.logging.Logger;
028:
029: import javax.xml.parsers.DocumentBuilder;
030: import javax.xml.parsers.DocumentBuilderFactory;
031: import javax.xml.parsers.ParserConfigurationException;
032:
033: import org.w3c.dom.Document;
034: import org.w3c.dom.Element;
035: import org.w3c.dom.NamedNodeMap;
036: import org.w3c.dom.Node;
037: import org.w3c.dom.NodeList;
038:
039: import org.xml.sax.SAXException;
040:
041: import org.apache.cxf.common.i18n.Message;
042: import org.apache.cxf.common.logging.LogUtils;
043: import org.apache.cxf.helpers.DOMUtils;
044: import org.apache.cxf.tools.common.ToolException;
045: import org.apache.cxf.wsdl.WSDLConstants;
046:
047: import org.apache.ws.commons.schema.XmlSchemaCollection;
048:
049: public final class ValidatorUtil {
050: private static final Logger LOG = LogUtils
051: .getL7dLogger(ValidatorUtil.class);
052:
053: private ValidatorUtil() {
054: }
055:
056: /**
057: * Get a list of schemas found in a wsdl Document.
058: * The list will include any schemas from imported wsdls.
059: *
060: * @param document The wsdl Document.
061: * @param baseURI The URI of the wsdl. Allows schemas with relative
062: * paths to be resolved.
063: * @return XmlSchemaCollection list
064: * @throws IOException
065: * @throws SAXException
066: */
067: public static List<XmlSchemaCollection> getSchemaList(
068: Document document, String baseURI) throws IOException,
069: SAXException {
070: List<XmlSchemaCollection> schemaList = new ArrayList<XmlSchemaCollection>();
071: if (document == null) {
072: return schemaList;
073: }
074: //
075: // If we are on windows we may have spaces in the uri
076: // which need to be escaped.
077: //
078: baseURI = baseURI.replaceAll(" ", "%20");
079: XmlSchemaCollection schemaCol = new XmlSchemaCollection();
080: NodeList nodes = document.getElementsByTagNameNS(
081: WSDLConstants.NU_SCHEMA_XSD, "schema");
082: for (int x = 0; x < nodes.getLength(); x++) {
083: Node schemaNode = nodes.item(x);
084: Element schemaEl = (Element) schemaNode;
085: String tns = schemaEl.getAttribute("targetNamespace");
086: try {
087: schemaCol.read(schemaEl, tns);
088: } catch (java.lang.RuntimeException ex) {
089: //
090: // Couldn't find schema... check if it's relative to wsdl.
091: // XXX - Using setBaseUri() on the XmlSchemaCollection,
092: // only seems to work for the first imported xsd... so pass
093: // in the baseURI here.
094: //
095: schemaCol.read(schemaEl, baseURI);
096: }
097: }
098: schemaList.add(schemaCol);
099:
100: // Now add schemas from imported wsdl files.
101: Map<String, Document> wsdlImports = getImportedWsdlMap(
102: document, baseURI);
103: for (Document wsdlImport : wsdlImports.values()) {
104: schemaList.addAll(getSchemaList(wsdlImport, baseURI));
105: }
106:
107: return schemaList;
108: }
109:
110: /**
111: * Get a map of wsdls imported by the given wsdl. Keys in the
112: * map are the imported namespaces. Values are the imported
113: * wsdl Documents.
114: *
115: * @param document The wsdl Document
116: * @param basePath The path of the wsdl
117: * @return map of imported wsdls
118: * @throws IOException
119: * @throws SAXException
120: */
121: public static Map<String, Document> getImportedWsdlMap(
122: Document document, String basePath) throws IOException,
123: SAXException {
124: Map<String, Document> docMap = new HashMap<String, Document>();
125: if (document == null) {
126: return docMap;
127: }
128:
129: DocumentBuilder docBuilder = null;
130: try {
131: DocumentBuilderFactory docFactory = DocumentBuilderFactory
132: .newInstance();
133: docFactory.setNamespaceAware(true);
134: docBuilder = docFactory.newDocumentBuilder();
135: } catch (ParserConfigurationException e) {
136: throw new ToolException(e);
137: }
138:
139: NodeList nodes = document.getElementsByTagNameNS(
140: WSDLConstants.WSDL11_NAMESPACE, "import");
141: //
142: // Remove the scheme part of a URI - need to escape spaces in
143: // case we are on Windows and have spaces in directory names.
144: //
145: String myBasePath = basePath;
146: try {
147: myBasePath = new URI(basePath.replaceAll(" ", "%20"))
148: .getPath();
149: } catch (java.net.URISyntaxException e1) {
150: // This will be problematic...
151: }
152: for (int x = 0; x < nodes.getLength(); x++) {
153: NamedNodeMap attributes = nodes.item(x).getAttributes();
154: String systemId;
155: String namespace = attributes.getNamedItem("namespace")
156: .getNodeValue();
157: // Is this ok?
158: if (docMap.containsKey(namespace)) {
159: continue;
160: }
161: try {
162: systemId = getImportedUrl(attributes.getNamedItem(
163: "location").getNodeValue(), myBasePath);
164: } catch (IOException ioe) {
165: throw new ToolException(ioe);
166: }
167: if (namespace != null && systemId != null) {
168: Document docImport = docBuilder.parse(systemId);
169: Node node = DOMUtils.getChild(docImport, null);
170: if (node != null
171: && !"definitions".equals(node.getLocalName())) {
172: Message msg = new Message("NOT_A_WSDLFILE", LOG,
173: systemId);
174: throw new ToolException(msg);
175: }
176: docMap
177: .putAll(getImportedWsdlMap(docImport,
178: myBasePath));
179: docMap.put(namespace, docImport);
180: }
181: }
182:
183: return docMap;
184: }
185:
186: private static String getImportedUrl(String theImportPath,
187: String baseURI) throws IOException {
188: File file = new File(theImportPath);
189: if (file != null && file.exists()) {
190: return file.toURI().toURL().toString();
191: }
192: // Import may have a relative path
193: File baseFile = new File(baseURI);
194: file = new File(baseFile.getParent(), theImportPath);
195: if (file != null && file.exists()) {
196: return file.toURI().toURL().toString();
197: }
198: return null;
199: }
200: }
|