ohair@286: /* ohair@286: * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package com.sun.tools.internal.ws.util; ohair@286: ohair@286: import com.sun.istack.internal.NotNull; ohair@286: import com.sun.tools.internal.ws.resources.WscompileMessages; ohair@286: import com.sun.tools.internal.ws.wscompile.WsimportListener; ohair@286: import com.sun.tools.internal.ws.wscompile.WsimportOptions; ohair@286: import com.sun.tools.internal.ws.wsdl.parser.DOMForest; ohair@286: import com.sun.tools.internal.ws.wsdl.parser.MetadataFinder; ohair@286: import com.sun.xml.internal.txw2.output.IndentingXMLStreamWriter; ohair@286: import com.sun.xml.internal.ws.api.server.PortAddressResolver; ohair@286: import com.sun.xml.internal.ws.streaming.SourceReaderFactory; ohair@286: import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants; ohair@286: import com.sun.xml.internal.ws.wsdl.writer.DocumentLocationResolver; ohair@286: import com.sun.xml.internal.ws.wsdl.writer.WSDLPatcher; ohair@286: import org.w3c.dom.Document; ohair@286: import org.w3c.dom.Element; ohair@286: import org.w3c.dom.Node; ohair@286: import org.w3c.dom.NodeList; ohair@286: ohair@286: import javax.xml.namespace.QName; ohair@286: import javax.xml.stream.XMLOutputFactory; ohair@286: import javax.xml.stream.XMLStreamException; ohair@286: import javax.xml.stream.XMLStreamReader; ohair@286: import javax.xml.stream.XMLStreamWriter; ohair@286: import javax.xml.transform.dom.DOMSource; ohair@286: import java.io.*; ohair@286: import java.net.MalformedURLException; ohair@286: import java.net.URL; ohair@286: import java.util.HashMap; ohair@286: import java.util.Map; ohair@286: import java.util.Set; ohair@286: ohair@286: /** ohair@286: * @author Rama Pulavarthi ohair@286: */ ohair@286: public class WSDLFetcher { ohair@286: private WsimportOptions options; ohair@286: private WsimportListener listener; ohair@286: public WSDLFetcher(WsimportOptions options, WsimportListener listener) { ohair@286: this.options = options; ohair@286: this.listener = listener; ohair@286: } ohair@286: ohair@286: ohair@286: /** ohair@286: * Fetches the wsdls in the DOMForest to the options.destDir ohair@286: * @param forest ohair@286: * @return ohair@286: * @throws IOException ohair@286: * @throws XMLStreamException ohair@286: * @throws FileNotFoundException ohair@286: */ ohair@286: public String fetchWsdls(MetadataFinder forest) throws IOException, XMLStreamException { ohair@286: String rootWsdl = null; ohair@286: for(String root: forest.getRootDocuments()) { ohair@286: rootWsdl = root; ohair@286: } ohair@286: ohair@286: Set externalRefs = forest.getExternalReferences(); ohair@286: Map documentMap = createDocumentMap(forest, getWSDLDownloadDir(), rootWsdl, externalRefs); ohair@286: String rootWsdlName = fetchFile(rootWsdl,forest, documentMap,getWSDLDownloadDir()); ohair@286: for(String reference: forest.getExternalReferences()) { ohair@286: fetchFile(reference,forest,documentMap,getWSDLDownloadDir()); ohair@286: } ohair@286: return WSDL_PATH +"/" + rootWsdlName; ohair@286: } ohair@286: ohair@286: private String fetchFile(final String doc, DOMForest forest, final Map documentMap, File destDir) throws IOException, XMLStreamException { ohair@286: ohair@286: DocumentLocationResolver docLocator = createDocResolver(doc, forest, documentMap); ohair@286: WSDLPatcher wsdlPatcher = new WSDLPatcher(new PortAddressResolver() { ohair@286: @Override ohair@286: public String getAddressFor(@NotNull QName serviceName, @NotNull String portName) { ohair@286: return null; ohair@286: } ohair@286: }, docLocator); ohair@286: ohair@286: //XMLInputFactory readerFactory = XMLInputFactory.newInstance(); ohair@286: //XMLStreamReader xsr = readerFactory.createXMLStreamReader(new DOMSource(forest.get(rootWsdl))); ohair@286: ohair@286: XMLStreamReader xsr = SourceReaderFactory.createSourceReader(new DOMSource(forest.get(doc)), false); ohair@286: XMLOutputFactory writerfactory = XMLOutputFactory.newInstance(); ohair@286: String resolvedRootWsdl = docLocator.getLocationFor(null, doc); ohair@286: File outFile = new File(destDir, resolvedRootWsdl); ohair@286: OutputStream os = new FileOutputStream(outFile); ohair@286: if(options.verbose) { ohair@286: listener.message(WscompileMessages.WSIMPORT_DOCUMENT_DOWNLOAD(doc,outFile)); ohair@286: } ohair@286: XMLStreamWriter xsw = writerfactory.createXMLStreamWriter(os); ohair@286: //DOMForest eats away the whitespace loosing all the indentation, so write it through ohair@286: // indenting writer for better readability of fetched documents ohair@286: IndentingXMLStreamWriter indentingWriter = new IndentingXMLStreamWriter(xsw); ohair@286: wsdlPatcher.bridge(xsr, indentingWriter); ohair@286: xsr.close(); ohair@286: xsw.close(); ohair@286: os.close(); ohair@286: options.addGeneratedFile(outFile); ohair@286: return resolvedRootWsdl; ohair@286: ohair@286: ohair@286: } ohair@286: private Map createDocumentMap(MetadataFinder forest, File baseDir, final String rootWsdl, Set externalReferences) { ohair@286: Map map = new HashMap(); ohair@286: String rootWsdlFileName = rootWsdl; ohair@286: String rootWsdlName; ohair@286: ohair@286: int slashIndex = rootWsdl.lastIndexOf("/"); ohair@286: if( slashIndex >= 0) { ohair@286: rootWsdlFileName = rootWsdl.substring(slashIndex+1); ohair@286: } ohair@286: if(!rootWsdlFileName.endsWith(WSDL_FILE_EXTENSION)) { ohair@286: Document rootWsdlDoc = forest.get(rootWsdl); ohair@286: NodeList serviceNodes = rootWsdlDoc.getElementsByTagNameNS(WSDLConstants.QNAME_SERVICE.getNamespaceURI(),WSDLConstants.QNAME_SERVICE.getLocalPart()); ohair@286: if(serviceNodes.getLength() == 0) ohair@286: rootWsdlName = "Service"; ohair@286: else { ohair@286: Node serviceNode = serviceNodes.item(0); ohair@286: String serviceName = ((Element)serviceNode).getAttribute( WSDLConstants.ATTR_NAME); ohair@286: rootWsdlName = serviceName; ohair@286: } ohair@286: rootWsdlFileName = rootWsdlName+ WSDL_FILE_EXTENSION; ohair@286: } else { ohair@286: rootWsdlName = rootWsdlFileName.substring(0,rootWsdlFileName.length()-5); ohair@286: } ohair@286: ohair@286: map.put(rootWsdl,sanitize(rootWsdlFileName)); ohair@286: ohair@286: int i =1; ohair@286: for(String ref: externalReferences) { ohair@286: Document refDoc = forest.get(ref); ohair@286: Element rootEl = refDoc.getDocumentElement(); ohair@286: String fileExtn; ohair@286: String fileName = null; ohair@286: int index = ref.lastIndexOf("/"); ohair@286: if (index >= 0) { ohair@286: fileName = ref.substring(index + 1); ohair@286: } ohair@286: if(rootEl.getLocalName().equals(WSDLConstants.QNAME_DEFINITIONS.getLocalPart()) && rootEl.getNamespaceURI().equals(WSDLConstants.NS_WSDL)) { ohair@286: fileExtn = WSDL_FILE_EXTENSION; ohair@286: } else if(rootEl.getLocalName().equals(WSDLConstants.QNAME_SCHEMA.getLocalPart()) && rootEl.getNamespaceURI().equals(WSDLConstants.NS_XMLNS)) { ohair@286: fileExtn = SCHEMA_FILE_EXTENSION; ohair@286: } else { ohair@286: fileExtn = ".xml"; ohair@286: } ohair@286: if(fileName != null && (fileName.endsWith(WSDL_FILE_EXTENSION) || fileName.endsWith(SCHEMA_FILE_EXTENSION))) { ohair@286: map.put(ref, rootWsdlName+"_"+fileName); ohair@286: } else { ohair@286: map.put(ref, rootWsdlName+"_metadata"+ (i++) + fileExtn); ohair@286: } ohair@286: } ohair@286: return map; ohair@286: } ohair@286: ohair@286: private DocumentLocationResolver createDocResolver(final String baseWsdl, final DOMForest forest, final Map documentMap) { ohair@286: ohair@286: return new DocumentLocationResolver() { ohair@286: public String getLocationFor(String namespaceURI, String systemId) { ohair@286: try { ohair@286: URL reference = new URL(new URL(baseWsdl),systemId); ohair@286: systemId = reference.toExternalForm(); ohair@286: } catch (MalformedURLException e) { ohair@286: throw new RuntimeException(e); ohair@286: } ohair@286: if(documentMap.get(systemId) != null) { ohair@286: return documentMap.get(systemId); ohair@286: } else { ohair@286: String parsedEntity = forest.getReferencedEntityMap().get(systemId); ohair@286: return documentMap.get(parsedEntity); ohair@286: } ohair@286: } ohair@286: }; ohair@286: } ohair@286: ohair@286: private String sanitize(String fileName) { ohair@286: fileName = fileName.replace('?', '.'); ohair@286: StringBuffer sb = new StringBuffer(fileName); ohair@286: for (int i = 0; i < sb.length(); i++) { ohair@286: char c = sb.charAt(i); ohair@286: if (Character.isLetterOrDigit(c) || ohair@286: (c == '/') || ohair@286: (c == '.') || ohair@286: (c == '_') || ohair@286: (c == ' ') || ohair@286: (c == '-')) { ohair@286: continue; ohair@286: } else { ohair@286: sb.setCharAt(i, '_'); ohair@286: } ohair@286: } ohair@286: return sb.toString(); ohair@286: } ohair@286: ohair@286: private File getWSDLDownloadDir() { ohair@286: File wsdlDir = new File(options.destDir,WSDL_PATH); ohair@286: wsdlDir.mkdirs(); ohair@286: return wsdlDir; ohair@286: } ohair@286: ohair@286: private static String WSDL_PATH="META-INF/wsdl"; ohair@286: private static String WSDL_FILE_EXTENSION=".wsdl"; ohair@286: private static String SCHEMA_FILE_EXTENSION=".xsd"; ohair@286: }