ohair@286: /* ohair@286: * Copyright (c) 1997, 2012, 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.wscompile; ohair@286: ohair@286: import com.sun.istack.internal.tools.ParallelWorldClassLoader; ohair@286: import com.sun.tools.internal.ws.ToolVersion; ohair@286: import com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceAp; ohair@286: import com.sun.tools.internal.ws.processor.modeler.wsdl.ConsoleErrorReporter; ohair@286: import com.sun.tools.internal.ws.resources.WscompileMessages; ohair@286: import com.sun.tools.internal.xjc.util.NullStream; ohair@286: import com.sun.xml.internal.txw2.TXW; ohair@286: import com.sun.xml.internal.txw2.TypedXmlWriter; ohair@286: import com.sun.xml.internal.txw2.annotation.XmlAttribute; ohair@286: import com.sun.xml.internal.txw2.annotation.XmlElement; ohair@286: import com.sun.xml.internal.txw2.output.StreamSerializer; ohair@286: import com.sun.xml.internal.ws.api.BindingID; ohair@286: import com.sun.xml.internal.ws.api.databinding.DatabindingConfig; ohair@286: import com.sun.xml.internal.ws.api.databinding.DatabindingFactory; ohair@286: import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo; ohair@286: import com.sun.xml.internal.ws.api.server.Container; ohair@286: import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension; ohair@286: import com.sun.xml.internal.ws.binding.WebServiceFeatureList; ohair@286: import com.sun.xml.internal.ws.model.AbstractSEIModelImpl; ohair@286: import com.sun.xml.internal.ws.util.ServiceFinder; ohair@286: import com.sun.xml.internal.ws.wsdl.writer.WSDLResolver; ohair@286: import org.xml.sax.SAXParseException; ohair@286: ohair@286: import javax.tools.DiagnosticCollector; ohair@286: import javax.tools.JavaCompiler; ohair@286: import javax.tools.JavaFileObject; ohair@286: import javax.tools.StandardJavaFileManager; ohair@286: import javax.tools.ToolProvider; ohair@286: import javax.xml.bind.annotation.XmlSeeAlso; ohair@286: import javax.xml.namespace.QName; ohair@286: import javax.xml.transform.Result; ohair@286: import javax.xml.transform.stream.StreamResult; ohair@286: import javax.xml.ws.EndpointReference; ohair@286: import javax.xml.ws.Holder; ohair@286: import java.io.BufferedOutputStream; ohair@286: import java.io.File; ohair@286: import java.io.FileNotFoundException; ohair@286: import java.io.FileOutputStream; ohair@286: import java.io.IOException; ohair@286: import java.io.OutputStream; ohair@286: import java.io.PrintStream; ohair@286: import java.net.URLClassLoader; ohair@286: import java.util.ArrayList; ohair@286: import java.util.Collection; ohair@286: import java.util.Collections; ohair@286: import java.util.HashMap; ohair@286: import java.util.Map; ohair@286: ohair@286: /** ohair@286: * @author Vivek Pandey ohair@286: */ ohair@286: ohair@286: /* ohair@286: * All annotation types are supported. ohair@286: */ ohair@286: public class WsgenTool { ohair@286: private final PrintStream out; ohair@286: private final WsgenOptions options = new WsgenOptions(); ohair@286: ohair@286: ohair@286: public WsgenTool(OutputStream out, Container container) { ohair@286: this.out = (out instanceof PrintStream)?(PrintStream)out:new PrintStream(out); ohair@286: this.container = container; ohair@286: } ohair@286: ohair@286: ohair@286: public WsgenTool(OutputStream out) { ohair@286: this(out, null); ohair@286: } ohair@286: ohair@286: public boolean run(String[] args){ ohair@286: final Listener listener = new Listener(); ohair@286: for (String arg : args) { ohair@286: if (arg.equals("-version")) { ohair@286: listener.message( ohair@286: WscompileMessages.WSGEN_VERSION(ToolVersion.VERSION.MAJOR_VERSION)); ohair@286: return true; ohair@286: } ohair@286: if (arg.equals("-fullversion")) { ohair@286: listener.message( ohair@286: WscompileMessages.WSGEN_FULLVERSION(ToolVersion.VERSION.toString())); ohair@286: return true; ohair@286: } ohair@286: } ohair@286: try { ohair@286: options.parseArguments(args); ohair@286: options.validate(); ohair@286: if(!buildModel(options.endpoint.getName(), listener)){ ohair@286: return false; ohair@286: } ohair@286: }catch (Options.WeAreDone done){ ohair@286: usage((WsgenOptions)done.getOptions()); ohair@286: }catch (BadCommandLineException e) { ohair@286: if(e.getMessage()!=null) { ohair@286: System.out.println(e.getMessage()); ohair@286: System.out.println(); ohair@286: } ohair@286: usage((WsgenOptions)e.getOptions()); ohair@286: return false; ohair@286: }catch(AbortException e){ ohair@286: //error might have been reported ohair@286: }finally{ ohair@286: if(!options.keep){ ohair@286: options.removeGeneratedFiles(); ohair@286: } ohair@286: } ohair@286: return true; ohair@286: } ohair@286: ohair@286: private final Container container; ohair@286: ohair@286: private int round = 0; ohair@286: ohair@286: /* ohair@286: * To take care of JDK6-JDK6u3, where 2.1 API classes are not there ohair@286: */ ohair@286: private static boolean useBootClasspath(Class clazz) { ohair@286: try { ohair@286: ParallelWorldClassLoader.toJarUrl(clazz.getResource('/'+clazz.getName().replace('.','/')+".class")); ohair@286: return true; ohair@286: } catch(Exception e) { ohair@286: return false; ohair@286: } ohair@286: } ohair@286: ohair@286: ohair@286: public boolean buildModel(String endpoint, Listener listener) throws BadCommandLineException { ohair@286: final ErrorReceiverFilter errReceiver = new ErrorReceiverFilter(listener); ohair@286: ohair@286: boolean bootCP = useBootClasspath(EndpointReference.class) || useBootClasspath(XmlSeeAlso.class); ohair@286: Collection args = new ArrayList(6 + (bootCP ? 1 : 0) + (options.nocompile ? 1 : 0) ohair@286: + (options.encoding != null ? 2 : 0)); ohair@286: args.add("-d"); ohair@286: args.add(options.destDir.getAbsolutePath()); ohair@286: args.add("-classpath"); ohair@286: args.add(options.classpath); ohair@286: args.add("-s"); ohair@286: args.add(options.sourceDir.getAbsolutePath()); ohair@286: if (options.nocompile) { ohair@286: args.add("-proc:only"); ohair@286: } ohair@286: if (options.encoding != null) { ohair@286: args.add("-encoding"); ohair@286: args.add(options.encoding); ohair@286: } ohair@286: if (bootCP) { ohair@286: args.add(new StringBuilder() ohair@286: .append("-Xbootclasspath/p:") ohair@286: .append(JavaCompilerHelper.getJarFile(EndpointReference.class)) ohair@286: .append(File.pathSeparator) ohair@286: .append(JavaCompilerHelper.getJarFile(XmlSeeAlso.class)).toString()); ohair@286: } ohair@286: ohair@286: JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); ohair@286: DiagnosticCollector diagnostics = new DiagnosticCollector(); ohair@286: StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); ohair@286: JavaCompiler.CompilationTask task = compiler.getTask( ohair@286: null, ohair@286: fileManager, ohair@286: diagnostics, ohair@286: args, ohair@286: Collections.singleton(endpoint.replaceAll("\\$", ".")), ohair@286: null); ohair@286: task.setProcessors(Collections.singleton(new WebServiceAp(options, out))); ohair@286: boolean result = task.call(); ohair@286: ohair@286: if (!result) { ohair@286: out.println(WscompileMessages.WSCOMPILE_ERROR(WscompileMessages.WSCOMPILE_COMPILATION_FAILED())); ohair@286: return false; ohair@286: } ohair@286: if (options.genWsdl) { ohair@286: DatabindingConfig config = new DatabindingConfig(); ohair@286: String tmpPath = options.destDir.getAbsolutePath()+ File.pathSeparator+options.classpath; ohair@286: ClassLoader classLoader = new URLClassLoader(Options.pathToURLs(tmpPath), ohair@286: this.getClass().getClassLoader()); ohair@286: Class endpointClass; ohair@286: try { ohair@286: endpointClass = classLoader.loadClass(endpoint); ohair@286: } catch (ClassNotFoundException e) { ohair@286: throw new BadCommandLineException(WscompileMessages.WSGEN_CLASS_NOT_FOUND(endpoint)); ohair@286: } ohair@286: ohair@286: BindingID bindingID = options.getBindingID(options.protocol); ohair@286: if (!options.protocolSet) { ohair@286: bindingID = BindingID.parse(endpointClass); ohair@286: } ohair@286: WebServiceFeatureList wsfeatures = new WebServiceFeatureList(endpointClass); ohair@286: // RuntimeModeler rtModeler = new RuntimeModeler(endpointClass, options.serviceName, bindingID, wsfeatures.toArray()); ohair@286: // rtModeler.setClassLoader(classLoader); ohair@286: if (options.portName != null) ohair@286: config.getMappingInfo().setPortName(options.portName);//rtModeler.setPortName(options.portName); ohair@286: // AbstractSEIModelImpl rtModel = rtModeler.buildRuntimeModel(); ohair@286: ohair@286: DatabindingFactory fac = DatabindingFactory.newInstance(); ohair@286: config.setEndpointClass(endpointClass); ohair@286: config.getMappingInfo().setServiceName(options.serviceName); ohair@286: config.setFeatures(wsfeatures.toArray()); ohair@286: config.setClassLoader(classLoader); ohair@286: config.getMappingInfo().setBindingID(bindingID); ohair@286: com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl)fac.createRuntime(config); ohair@286: ohair@286: final File[] wsdlFileName = new File[1]; // used to capture the generated WSDL file. ohair@286: final Map schemaFiles = new HashMap(); ohair@286: ohair@286: WSDLGenInfo wsdlGenInfo = new WSDLGenInfo(); ohair@286: wsdlGenInfo.setWsdlResolver( ohair@286: new WSDLResolver() { ohair@286: private File toFile(String suggestedFilename) { ohair@286: return new File(options.nonclassDestDir, suggestedFilename); ohair@286: } ohair@286: private Result toResult(File file) { ohair@286: Result result; ohair@286: try { ohair@286: result = new StreamResult(new FileOutputStream(file)); ohair@286: result.setSystemId(file.getPath().replace('\\', '/')); ohair@286: } catch (FileNotFoundException e) { ohair@286: errReceiver.error(e); ohair@286: return null; ohair@286: } ohair@286: return result; ohair@286: } ohair@286: ohair@286: public Result getWSDL(String suggestedFilename) { ohair@286: File f = toFile(suggestedFilename); ohair@286: wsdlFileName[0] = f; ohair@286: return toResult(f); ohair@286: } ohair@286: public Result getSchemaOutput(String namespace, String suggestedFilename) { ohair@286: if (namespace == null) ohair@286: return null; ohair@286: File f = toFile(suggestedFilename); ohair@286: schemaFiles.put(namespace,f); ohair@286: return toResult(f); ohair@286: } ohair@286: public Result getAbstractWSDL(Holder filename) { ohair@286: return toResult(toFile(filename.value)); ohair@286: } ohair@286: public Result getSchemaOutput(String namespace, Holder filename) { ohair@286: return getSchemaOutput(namespace, filename.value); ohair@286: } ohair@286: // TODO pass correct impl's class name ohair@286: }); ohair@286: ohair@286: wsdlGenInfo.setContainer(container); ohair@286: wsdlGenInfo.setExtensions(ServiceFinder.find(WSDLGeneratorExtension.class).toArray()); ohair@286: wsdlGenInfo.setInlineSchemas(options.inlineSchemas); ohair@286: rt.generateWSDL(wsdlGenInfo); ohair@286: ohair@286: ohair@286: if(options.wsgenReport!=null) ohair@286: generateWsgenReport(endpointClass,(AbstractSEIModelImpl)rt.getModel(),wsdlFileName[0],schemaFiles); ohair@286: } ohair@286: return true; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Generates a small XML file that captures the key activity of wsgen, ohair@286: * so that test harness can pick up artifacts. ohair@286: */ ohair@286: private void generateWsgenReport(Class endpointClass, AbstractSEIModelImpl rtModel, File wsdlFile, Map schemaFiles) { ohair@286: try { ohair@286: ReportOutput.Report report = TXW.create(ReportOutput.Report.class, ohair@286: new StreamSerializer(new BufferedOutputStream(new FileOutputStream(options.wsgenReport)))); ohair@286: ohair@286: report.wsdl(wsdlFile.getAbsolutePath()); ohair@286: ReportOutput.writeQName(rtModel.getServiceQName(), report.service()); ohair@286: ReportOutput.writeQName(rtModel.getPortName(), report.port()); ohair@286: ReportOutput.writeQName(rtModel.getPortTypeName(), report.portType()); ohair@286: ohair@286: report.implClass(endpointClass.getName()); ohair@286: ohair@286: for (Map.Entry e : schemaFiles.entrySet()) { ohair@286: ReportOutput.Schema s = report.schema(); ohair@286: s.ns(e.getKey()); ohair@286: s.location(e.getValue().getAbsolutePath()); ohair@286: } ohair@286: ohair@286: report.commit(); ohair@286: } catch (IOException e) { ohair@286: // this is code for the test, so we can be lousy in the error handling ohair@286: throw new Error(e); ohair@286: } ohair@286: } ohair@286: ohair@286: /** ohair@286: * "Namespace" for code needed to generate the report file. ohair@286: */ ohair@286: static class ReportOutput { ohair@286: @XmlElement("report") ohair@286: interface Report extends TypedXmlWriter { ohair@286: @XmlElement ohair@286: void wsdl(String file); // location of WSDL ohair@286: @XmlElement ohair@286: QualifiedName portType(); ohair@286: @XmlElement ohair@286: QualifiedName service(); ohair@286: @XmlElement ohair@286: QualifiedName port(); ohair@286: ohair@286: /** ohair@286: * Name of the class that has {@link javax.jws.WebService}. ohair@286: */ ohair@286: @XmlElement ohair@286: void implClass(String name); ohair@286: ohair@286: @XmlElement ohair@286: Schema schema(); ohair@286: } ohair@286: ohair@286: interface QualifiedName extends TypedXmlWriter { ohair@286: @XmlAttribute ohair@286: void uri(String ns); ohair@286: @XmlAttribute ohair@286: void localName(String localName); ohair@286: } ohair@286: ohair@286: interface Schema extends TypedXmlWriter { ohair@286: @XmlAttribute ohair@286: void ns(String ns); ohair@286: @XmlAttribute ohair@286: void location(String filePath); ohair@286: } ohair@286: ohair@286: private static void writeQName( QName n, QualifiedName w ) { ohair@286: w.uri(n.getNamespaceURI()); ohair@286: w.localName(n.getLocalPart()); ohair@286: } ohair@286: } ohair@286: ohair@286: protected void usage(WsgenOptions options) { ohair@286: // Just don't see any point in passing WsgenOptions ohair@286: // BadCommandLineException also shouldn't have options ohair@286: if (options == null) ohair@286: options = this.options; ohair@286: System.out.println(WscompileMessages.WSGEN_HELP("WSGEN", options.protocols, options.nonstdProtocols.keySet())); ohair@286: System.out.println(WscompileMessages.WSGEN_USAGE_EXAMPLES()); ohair@286: } ohair@286: ohair@286: class Listener extends WsimportListener { ohair@286: ConsoleErrorReporter cer = new ConsoleErrorReporter(out == null ? new PrintStream(new NullStream()) : out); ohair@286: ohair@286: @Override ohair@286: public void generatedFile(String fileName) { ohair@286: message(fileName); ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void message(String msg) { ohair@286: out.println(msg); ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void error(SAXParseException exception) { ohair@286: cer.error(exception); ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void fatalError(SAXParseException exception) { ohair@286: cer.fatalError(exception); ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void warning(SAXParseException exception) { ohair@286: cer.warning(exception); ohair@286: } ohair@286: ohair@286: @Override ohair@286: public void info(SAXParseException exception) { ohair@286: cer.info(exception); ohair@286: } ohair@286: } ohair@286: }