449 lines
17 KiB
Java
449 lines
17 KiB
Java
/*
|
|
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code 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
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
package com.sun.tools.internal.ws.wscompile;
|
|
|
|
import com.oracle.webservices.internal.api.databinding.WSDLResolver;
|
|
import com.sun.istack.internal.tools.ParallelWorldClassLoader;
|
|
import com.sun.tools.internal.ws.ToolVersion;
|
|
import com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceAp;
|
|
import com.sun.tools.internal.ws.processor.modeler.wsdl.ConsoleErrorReporter;
|
|
import com.sun.tools.internal.ws.resources.WscompileMessages;
|
|
import com.sun.tools.internal.xjc.util.NullStream;
|
|
import com.sun.xml.internal.txw2.TXW;
|
|
import com.sun.xml.internal.txw2.TypedXmlWriter;
|
|
import com.sun.xml.internal.txw2.annotation.XmlAttribute;
|
|
import com.sun.xml.internal.txw2.annotation.XmlElement;
|
|
import com.sun.xml.internal.txw2.output.StreamSerializer;
|
|
import com.sun.xml.internal.ws.api.BindingID;
|
|
import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
|
|
import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
|
|
import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo;
|
|
import com.sun.xml.internal.ws.api.server.Container;
|
|
import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension;
|
|
import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
|
|
import com.sun.xml.internal.ws.model.ExternalMetadataReader;
|
|
import com.sun.xml.internal.ws.model.AbstractSEIModelImpl;
|
|
import com.sun.xml.internal.ws.util.ServiceFinder;
|
|
import org.xml.sax.SAXParseException;
|
|
|
|
import javax.tools.DiagnosticCollector;
|
|
import javax.tools.JavaCompiler;
|
|
import javax.tools.JavaFileObject;
|
|
import javax.tools.StandardJavaFileManager;
|
|
import javax.tools.ToolProvider;
|
|
import javax.xml.bind.annotation.XmlSeeAlso;
|
|
import javax.xml.namespace.QName;
|
|
import javax.xml.transform.Result;
|
|
import javax.xml.transform.stream.StreamResult;
|
|
import javax.xml.ws.EndpointReference;
|
|
import javax.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.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* @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;
|
|
|
|
/*
|
|
* To take care of JDK6-JDK6u3, where 2.1 API classes are not there
|
|
*/
|
|
private static boolean useBootClasspath(Class clazz) {
|
|
try {
|
|
ParallelWorldClassLoader.toJarUrl(clazz.getResource('/' + clazz.getName().replace('.', '/') + ".class"));
|
|
return true;
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param endpoint
|
|
* @param listener
|
|
* @return
|
|
* @throws BadCommandLineException
|
|
*/
|
|
public boolean buildModel(String endpoint, Listener listener) throws BadCommandLineException {
|
|
final ErrorReceiverFilter errReceiver = new ErrorReceiverFilter(listener);
|
|
|
|
boolean bootCP = useBootClasspath(EndpointReference.class) || useBootClasspath(XmlSeeAlso.class);
|
|
List<String> args = new ArrayList<String>(6 + (bootCP ? 1 : 0) + (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 (bootCP) {
|
|
args.add(new StringBuilder()
|
|
.append("-Xbootclasspath/p:")
|
|
.append(JavaCompilerHelper.getJarFile(EndpointReference.class))
|
|
.append(File.pathSeparator)
|
|
.append(JavaCompilerHelper.getJarFile(XmlSeeAlso.class)).toString());
|
|
}
|
|
if (options.javacOptions != null) {
|
|
args.addAll(options.getJavacOptions(args, listener));
|
|
}
|
|
|
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();// compiler = JavacTool.create();
|
|
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
|
|
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<String> externalMetadataFileNames = options.externalMetadataFiles;
|
|
boolean disableXmlSecurity = options.disableXmlSecurity;
|
|
if (externalMetadataFileNames != null && externalMetadataFileNames.size() > 0) {
|
|
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.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl) fac.createRuntime(config);
|
|
|
|
final File[] wsdlFileName = new File[1]; // used to capture the generated WSDL file.
|
|
final Map<String, File> schemaFiles = new HashMap<String, File>();
|
|
|
|
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<String> filename) {
|
|
return toResult(toFile(filename.value));
|
|
}
|
|
|
|
@Override
|
|
public Result getSchemaOutput(String namespace, Holder<String> filename) {
|
|
return getSchemaOutput(namespace, filename.value);
|
|
}
|
|
// TODO pass correct impl's class name
|
|
});
|
|
|
|
wsdlGenInfo.setContainer(container);
|
|
wsdlGenInfo.setExtensions(ServiceFinder.find(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 List<File> getExternalFiles(List<String> exts) {
|
|
List<File> files = new ArrayList<File>();
|
|
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<String, File> 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<String, File> 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 javax.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);
|
|
}
|
|
}
|
|
}
|