All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.tools.ws.wscompile.WsgenTool Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package com.sun.tools.ws.wscompile;

import com.oracle.webservices.api.databinding.WSDLResolver;
import com.sun.tools.ws.ToolVersion;
import com.sun.tools.ws.processor.modeler.annotation.WebServiceAp;
import com.sun.tools.ws.processor.modeler.wsdl.ConsoleErrorReporter;
import com.sun.tools.ws.resources.WscompileMessages;
import com.sun.tools.xjc.util.NullStream;
import com.sun.xml.txw2.TXW;
import com.sun.xml.txw2.TypedXmlWriter;
import com.sun.xml.txw2.annotation.XmlAttribute;
import com.sun.xml.txw2.annotation.XmlElement;
import com.sun.xml.txw2.output.StreamSerializer;
import com.sun.xml.ws.api.BindingID;
import com.sun.xml.ws.api.databinding.DatabindingConfig;
import com.sun.xml.ws.api.databinding.DatabindingFactory;
import com.sun.xml.ws.api.databinding.WSDLGenInfo;
import com.sun.xml.ws.api.server.Container;
import com.sun.xml.ws.api.wsdl.writer.WSDLGeneratorExtension;
import com.sun.xml.ws.binding.WebServiceFeatureList;
import com.sun.xml.ws.model.ExternalMetadataReader;
import com.sun.xml.ws.model.AbstractSEIModelImpl;
import com.sun.xml.ws.util.ServiceFinder;
import org.xml.sax.SAXParseException;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import jakarta.xml.ws.Holder;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ServiceLoader;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import org.xml.sax.ext.Locator2Impl;

/**
 * @author Vivek Pandey
 */

/*
 * All annotation types are supported.
 */
public class WsgenTool {
    private final PrintStream out;
    private final WsgenOptions options = new WsgenOptions();


    public WsgenTool(OutputStream out, Container container) {
        this.out = (out instanceof PrintStream) ? (PrintStream) out : new PrintStream(out);
        this.container = container;
    }


    public WsgenTool(OutputStream out) {
        this(out, null);
    }

    public boolean run(String[] args) {
        final Listener listener = new Listener();
        for (String arg : args) {
            if (arg.equals("-version")) {
                listener.message(
                        WscompileMessages.WSGEN_VERSION(ToolVersion.VERSION.MAJOR_VERSION));
                return true;
            }
            if (arg.equals("-fullversion")) {
                listener.message(
                        WscompileMessages.WSGEN_FULLVERSION(ToolVersion.VERSION.toString()));
                return true;
            }
        }
        try {
            options.parseArguments(args);
            options.validate();
            if (!buildModel(options.endpoint.getName(), listener)) {
                return false;
            }
        } catch (Options.WeAreDone done) {
            usage(done.getOptions());
        } catch (BadCommandLineException e) {
            if (e.getMessage() != null) {
                System.out.println(e.getMessage());
                System.out.println();
            }
            usage(e.getOptions());
            return false;
        } catch (AbortException e) {
            //error might have been reported
        } finally {
            if (!options.keep) {
                options.removeGeneratedFiles();
            }
        }
        return true;
    }

    private final Container container;

    /**
     *
     */
    public boolean buildModel(String endpoint, WsimportListener listener) throws BadCommandLineException {
        final ErrorReceiverFilter errReceiver = new ErrorReceiverFilter(listener);

        if (!options.nosource) {
            List args = new ArrayList<>(6 + (options.nocompile ? 1 : 0)
                    + (options.encoding != null ? 2 : 0));

            args.add("-d");
            args.add(options.destDir.getAbsolutePath());
            args.add("-classpath");
            args.add(options.classpath);
            args.add("-s");
            args.add(options.sourceDir.getAbsolutePath());
            if (options.nocompile) {
                args.add("-proc:only");
            }
            if (options.encoding != null) {
                args.add("-encoding");
                args.add(options.encoding);
            }
            if (options.javacOptions != null) {
                args.addAll(options.getJavacOptions(args, listener));
            }

            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            if (compiler == null) {
                out.println(WscompileMessages.WSCOMPILE_CANT_GET_COMPILER(property("java.home"), property("java.version"), property("java.vendor")));
                return false;
            }
            DiagnosticListener diagnostics = diagnostic -> {
                boolean fromFile = diagnostic.getSource() != null;
                StringBuilder message = new StringBuilder();
                if (fromFile) {
                    message.append(diagnostic.getSource().getName());
                }
                message.append(diagnostic.getMessage(Locale.getDefault()));
                if (fromFile) {
                    message.append("");
                }
                switch (diagnostic.getKind()) {
                    case ERROR:
                        Locator2Impl l = new Locator2Impl();
                        if (fromFile) {
                            l.setSystemId(diagnostic.getSource().getName());
                        } else {
                            l.setSystemId(null);
                        }
                        l.setLineNumber((int) diagnostic.getLineNumber());
                        l.setColumnNumber((int) diagnostic.getColumnNumber());
                        SAXParseException ex = new SAXParseException(message.toString(), l);
                        listener.error(ex);
                        break;
                    case MANDATORY_WARNING:
                    case WARNING:
                        listener.message(message.toString());
                        break;
                    default:
                        if (options.verbose) {
                            listener.message(message.toString());
                        }
                }
            };

            StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
            JavaCompiler.CompilationTask task = compiler.getTask(
                    null,
                    fileManager,
                    diagnostics,
                    args,
                    Collections.singleton(endpoint.replaceAll("\\$", ".")),
                    null);
            task.setProcessors(Collections.singleton(new WebServiceAp(options, out)));
            boolean result = task.call();

            if (!result) {
                out.println(WscompileMessages.WSCOMPILE_ERROR(WscompileMessages.WSCOMPILE_COMPILATION_FAILED()));
                return false;
            }
        }
        if (options.genWsdl) {
            DatabindingConfig config = new DatabindingConfig();

            List externalMetadataFileNames = options.externalMetadataFiles;
            boolean disableXmlSecurity = options.disableXmlSecurity;
            if (externalMetadataFileNames != null && !externalMetadataFileNames.isEmpty()) {
                config.setMetadataReader(new ExternalMetadataReader(getExternalFiles(externalMetadataFileNames), null, null, true, disableXmlSecurity));
            }

            String tmpPath = options.destDir.getAbsolutePath() + File.pathSeparator + options.classpath;
            ClassLoader classLoader = new URLClassLoader(Options.pathToURLs(tmpPath),
                    this.getClass().getClassLoader());
            Class endpointClass;
            try {
                endpointClass = classLoader.loadClass(endpoint);
            } catch (ClassNotFoundException e) {
                throw new BadCommandLineException(WscompileMessages.WSGEN_CLASS_NOT_FOUND(endpoint));
            }

            BindingID bindingID = options.getBindingID(options.protocol);
            if (!options.protocolSet) {
                bindingID = BindingID.parse(endpointClass);
            }
            WebServiceFeatureList wsfeatures = new WebServiceFeatureList(endpointClass);
//            RuntimeModeler rtModeler = new RuntimeModeler(endpointClass, options.serviceName, bindingID, wsfeatures.toArray());
//            rtModeler.setClassLoader(classLoader);
            if (options.portName != null)
                config.getMappingInfo().setPortName(options.portName);//rtModeler.setPortName(options.portName);
//            AbstractSEIModelImpl rtModel = rtModeler.buildRuntimeModel();

            DatabindingFactory fac = DatabindingFactory.newInstance();
            config.setEndpointClass(endpointClass);
            config.getMappingInfo().setServiceName(options.serviceName);
            config.setFeatures(wsfeatures.toArray());
            config.setClassLoader(classLoader);
            config.getMappingInfo().setBindingID(bindingID);
            com.sun.xml.ws.db.DatabindingImpl rt = (com.sun.xml.ws.db.DatabindingImpl) fac.createRuntime(config);

            final File[] wsdlFileName = new File[1]; // used to capture the generated WSDL file.
            final Map schemaFiles = new HashMap<>();

            WSDLGenInfo wsdlGenInfo = new WSDLGenInfo();
            wsdlGenInfo.setSecureXmlProcessingDisabled(disableXmlSecurity);

            wsdlGenInfo.setWsdlResolver(
                    new WSDLResolver() {
                        private File toFile(String suggestedFilename) {
                            return new File(options.nonclassDestDir, suggestedFilename);
                        }

                        private Result toResult(File file) {
                            Result result;
                            try {
                                result = new StreamResult(new FileOutputStream(file));
                                result.setSystemId(file.getPath().replace('\\', '/'));
                            } catch (FileNotFoundException e) {
                                errReceiver.error(e);
                                return null;
                            }
                            return result;
                        }

                        @Override
                        public Result getWSDL(String suggestedFilename) {
                            File f = toFile(suggestedFilename);
                            wsdlFileName[0] = f;
                            return toResult(f);
                        }

                        public Result getSchemaOutput(String namespace, String suggestedFilename) {
                            if (namespace == null)
                                return null;
                            File f = toFile(suggestedFilename);
                            schemaFiles.put(namespace, f);
                            return toResult(f);
                        }

                        @Override
                        public Result getAbstractWSDL(Holder filename) {
                            return toResult(toFile(filename.value));
                        }

                        @Override
                        public Result getSchemaOutput(String namespace, Holder filename) {
                            return getSchemaOutput(namespace, filename.value);
                        }
                        // TODO pass correct impl's class name
                    });

            wsdlGenInfo.setContainer(container);
            wsdlGenInfo.setExtensions(ServiceFinder.find(WSDLGeneratorExtension.class, ServiceLoader.load(WSDLGeneratorExtension.class)).toArray());
            wsdlGenInfo.setInlineSchemas(options.inlineSchemas);
            rt.generateWSDL(wsdlGenInfo);


            if (options.wsgenReport != null)
                generateWsgenReport(endpointClass, (AbstractSEIModelImpl) rt.getModel(), wsdlFileName[0], schemaFiles);
        }
        return true;
    }

    private String property(String key) {
        try {
            String property = System.getProperty(key);
            return property != null ? property : "UNKNOWN";
        } catch (SecurityException ignored) {
            return "UNKNOWN";
        }
    }

    private List getExternalFiles(List exts) {
        List files = new ArrayList<>();
        for (String ext : exts) {
            // first try absolute path ...
            File file = new File(ext);
            if (!file.exists()) {
                // then relative path ...
                file = new File(options.sourceDir.getAbsolutePath() + File.separator + ext);
            }
            files.add(file);
        }
        return files;
    }

    /**
     * Generates a small XML file that captures the key activity of wsgen,
     * so that test harness can pick up artifacts.
     */
    private void generateWsgenReport(Class endpointClass, AbstractSEIModelImpl rtModel, File wsdlFile, Map schemaFiles) {
        try {
            ReportOutput.Report report = TXW.create(ReportOutput.Report.class,
                    new StreamSerializer(new BufferedOutputStream(new FileOutputStream(options.wsgenReport))));

            report.wsdl(wsdlFile.getAbsolutePath());
            ReportOutput.writeQName(rtModel.getServiceQName(), report.service());
            ReportOutput.writeQName(rtModel.getPortName(), report.port());
            ReportOutput.writeQName(rtModel.getPortTypeName(), report.portType());

            report.implClass(endpointClass.getName());

            for (Map.Entry e : schemaFiles.entrySet()) {
                ReportOutput.Schema s = report.schema();
                s.ns(e.getKey());
                s.location(e.getValue().getAbsolutePath());
            }

            report.commit();
        } catch (IOException e) {
            // this is code for the test, so we can be lousy in the error handling
            throw new Error(e);
        }
    }

    /**
     * "Namespace" for code needed to generate the report file.
     */
    static class ReportOutput {
        @XmlElement("report")
        interface Report extends TypedXmlWriter {
            @XmlElement
            void wsdl(String file); // location of WSDL

            @XmlElement
            QualifiedName portType();

            @XmlElement
            QualifiedName service();

            @XmlElement
            QualifiedName port();

            /**
             * Name of the class that has {@link jakarta.jws.WebService}.
             */
            @XmlElement
            void implClass(String name);

            @XmlElement
            Schema schema();
        }

        interface QualifiedName extends TypedXmlWriter {
            @XmlAttribute
            void uri(String ns);

            @XmlAttribute
            void localName(String localName);
        }

        interface Schema extends TypedXmlWriter {
            @XmlAttribute
            void ns(String ns);

            @XmlAttribute
            void location(String filePath);
        }

        private static void writeQName(QName n, QualifiedName w) {
            w.uri(n.getNamespaceURI());
            w.localName(n.getLocalPart());
        }
    }

    protected void usage(Options options) {
        // Just don't see any point in passing WsgenOptions
        // BadCommandLineException also shouldn't have options
        if (options == null)
            options = this.options;
        if (options instanceof WsgenOptions) {
            System.out.println(WscompileMessages.WSGEN_HELP("WSGEN",
                    ((WsgenOptions)options).protocols,
                    ((WsgenOptions)options).nonstdProtocols.keySet()));
            System.out.println(WscompileMessages.WSGEN_USAGE_EXTENSIONS());
            System.out.println(WscompileMessages.WSGEN_USAGE_EXAMPLES());
        }
    }

    class Listener extends WsimportListener {
        ConsoleErrorReporter cer = new ConsoleErrorReporter(out == null ? new PrintStream(new NullStream()) : out);

        @Override
        public void generatedFile(String fileName) {
            message(fileName);
        }

        @Override
        public void message(String msg) {
            out.println(msg);
        }

        @Override
        public void error(SAXParseException exception) {
            cer.error(exception);
        }

        @Override
        public void fatalError(SAXParseException exception) {
            cer.fatalError(exception);
        }

        @Override
        public void warning(SAXParseException exception) {
            cer.warning(exception);
        }

        @Override
        public void info(SAXParseException exception) {
            cer.info(exception);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy