Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.internal.ws.wscompile;
28 import com.sun.istack.internal.tools.ParallelWorldClassLoader;
29 import com.sun.tools.internal.ws.ToolVersion;
30 import com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceAp;
31 import com.sun.tools.internal.ws.processor.modeler.wsdl.ConsoleErrorReporter;
32 import com.sun.tools.internal.ws.resources.WscompileMessages;
33 import com.sun.tools.internal.xjc.util.NullStream;
34 import com.sun.xml.internal.txw2.TXW;
35 import com.sun.xml.internal.txw2.TypedXmlWriter;
36 import com.sun.xml.internal.txw2.annotation.XmlAttribute;
37 import com.sun.xml.internal.txw2.annotation.XmlElement;
38 import com.sun.xml.internal.txw2.output.StreamSerializer;
39 import com.sun.xml.internal.ws.api.BindingID;
40 import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
41 import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
42 import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo;
43 import com.sun.xml.internal.ws.api.server.Container;
44 import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension;
45 import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
46 import com.sun.xml.internal.ws.model.AbstractSEIModelImpl;
47 import com.sun.xml.internal.ws.util.ServiceFinder;
48 import com.sun.xml.internal.ws.wsdl.writer.WSDLResolver;
49 import org.xml.sax.SAXParseException;
51 import javax.tools.DiagnosticCollector;
52 import javax.tools.JavaCompiler;
53 import javax.tools.JavaFileObject;
54 import javax.tools.StandardJavaFileManager;
55 import javax.tools.ToolProvider;
56 import javax.xml.bind.annotation.XmlSeeAlso;
57 import javax.xml.namespace.QName;
58 import javax.xml.transform.Result;
59 import javax.xml.transform.stream.StreamResult;
60 import javax.xml.ws.EndpointReference;
61 import javax.xml.ws.Holder;
62 import java.io.BufferedOutputStream;
63 import java.io.File;
64 import java.io.FileNotFoundException;
65 import java.io.FileOutputStream;
66 import java.io.IOException;
67 import java.io.OutputStream;
68 import java.io.PrintStream;
69 import java.net.URLClassLoader;
70 import java.util.ArrayList;
71 import java.util.Collection;
72 import java.util.Collections;
73 import java.util.HashMap;
74 import java.util.Map;
76 /**
77 * @author Vivek Pandey
78 */
80 /*
81 * All annotation types are supported.
82 */
83 public class WsgenTool {
84 private final PrintStream out;
85 private final WsgenOptions options = new WsgenOptions();
88 public WsgenTool(OutputStream out, Container container) {
89 this.out = (out instanceof PrintStream)?(PrintStream)out:new PrintStream(out);
90 this.container = container;
91 }
94 public WsgenTool(OutputStream out) {
95 this(out, null);
96 }
98 public boolean run(String[] args){
99 final Listener listener = new Listener();
100 for (String arg : args) {
101 if (arg.equals("-version")) {
102 listener.message(
103 WscompileMessages.WSGEN_VERSION(ToolVersion.VERSION.MAJOR_VERSION));
104 return true;
105 }
106 if (arg.equals("-fullversion")) {
107 listener.message(
108 WscompileMessages.WSGEN_FULLVERSION(ToolVersion.VERSION.toString()));
109 return true;
110 }
111 }
112 try {
113 options.parseArguments(args);
114 options.validate();
115 if(!buildModel(options.endpoint.getName(), listener)){
116 return false;
117 }
118 }catch (Options.WeAreDone done){
119 usage((WsgenOptions)done.getOptions());
120 }catch (BadCommandLineException e) {
121 if(e.getMessage()!=null) {
122 System.out.println(e.getMessage());
123 System.out.println();
124 }
125 usage((WsgenOptions)e.getOptions());
126 return false;
127 }catch(AbortException e){
128 //error might have been reported
129 }finally{
130 if(!options.keep){
131 options.removeGeneratedFiles();
132 }
133 }
134 return true;
135 }
137 private final Container container;
139 private int round = 0;
141 /*
142 * To take care of JDK6-JDK6u3, where 2.1 API classes are not there
143 */
144 private static boolean useBootClasspath(Class clazz) {
145 try {
146 ParallelWorldClassLoader.toJarUrl(clazz.getResource('/'+clazz.getName().replace('.','/')+".class"));
147 return true;
148 } catch(Exception e) {
149 return false;
150 }
151 }
154 public boolean buildModel(String endpoint, Listener listener) throws BadCommandLineException {
155 final ErrorReceiverFilter errReceiver = new ErrorReceiverFilter(listener);
157 boolean bootCP = useBootClasspath(EndpointReference.class) || useBootClasspath(XmlSeeAlso.class);
158 Collection<String> args = new ArrayList<String>(6 + (bootCP ? 1 : 0) + (options.nocompile ? 1 : 0)
159 + (options.encoding != null ? 2 : 0));
160 args.add("-d");
161 args.add(options.destDir.getAbsolutePath());
162 args.add("-classpath");
163 args.add(options.classpath);
164 args.add("-s");
165 args.add(options.sourceDir.getAbsolutePath());
166 if (options.nocompile) {
167 args.add("-proc:only");
168 }
169 if (options.encoding != null) {
170 args.add("-encoding");
171 args.add(options.encoding);
172 }
173 if (bootCP) {
174 args.add(new StringBuilder()
175 .append("-Xbootclasspath/p:")
176 .append(JavaCompilerHelper.getJarFile(EndpointReference.class))
177 .append(File.pathSeparator)
178 .append(JavaCompilerHelper.getJarFile(XmlSeeAlso.class)).toString());
179 }
181 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
182 DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
183 StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
184 JavaCompiler.CompilationTask task = compiler.getTask(
185 null,
186 fileManager,
187 diagnostics,
188 args,
189 Collections.singleton(endpoint.replaceAll("\\$", ".")),
190 null);
191 task.setProcessors(Collections.singleton(new WebServiceAp(options, out)));
192 boolean result = task.call();
194 if (!result) {
195 out.println(WscompileMessages.WSCOMPILE_ERROR(WscompileMessages.WSCOMPILE_COMPILATION_FAILED()));
196 return false;
197 }
198 if (options.genWsdl) {
199 DatabindingConfig config = new DatabindingConfig();
200 String tmpPath = options.destDir.getAbsolutePath()+ File.pathSeparator+options.classpath;
201 ClassLoader classLoader = new URLClassLoader(Options.pathToURLs(tmpPath),
202 this.getClass().getClassLoader());
203 Class<?> endpointClass;
204 try {
205 endpointClass = classLoader.loadClass(endpoint);
206 } catch (ClassNotFoundException e) {
207 throw new BadCommandLineException(WscompileMessages.WSGEN_CLASS_NOT_FOUND(endpoint));
208 }
210 BindingID bindingID = options.getBindingID(options.protocol);
211 if (!options.protocolSet) {
212 bindingID = BindingID.parse(endpointClass);
213 }
214 WebServiceFeatureList wsfeatures = new WebServiceFeatureList(endpointClass);
215 // RuntimeModeler rtModeler = new RuntimeModeler(endpointClass, options.serviceName, bindingID, wsfeatures.toArray());
216 // rtModeler.setClassLoader(classLoader);
217 if (options.portName != null)
218 config.getMappingInfo().setPortName(options.portName);//rtModeler.setPortName(options.portName);
219 // AbstractSEIModelImpl rtModel = rtModeler.buildRuntimeModel();
221 DatabindingFactory fac = DatabindingFactory.newInstance();
222 config.setEndpointClass(endpointClass);
223 config.getMappingInfo().setServiceName(options.serviceName);
224 config.setFeatures(wsfeatures.toArray());
225 config.setClassLoader(classLoader);
226 config.getMappingInfo().setBindingID(bindingID);
227 com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl)fac.createRuntime(config);
229 final File[] wsdlFileName = new File[1]; // used to capture the generated WSDL file.
230 final Map<String,File> schemaFiles = new HashMap<String,File>();
232 WSDLGenInfo wsdlGenInfo = new WSDLGenInfo();
233 wsdlGenInfo.setWsdlResolver(
234 new WSDLResolver() {
235 private File toFile(String suggestedFilename) {
236 return new File(options.nonclassDestDir, suggestedFilename);
237 }
238 private Result toResult(File file) {
239 Result result;
240 try {
241 result = new StreamResult(new FileOutputStream(file));
242 result.setSystemId(file.getPath().replace('\\', '/'));
243 } catch (FileNotFoundException e) {
244 errReceiver.error(e);
245 return null;
246 }
247 return result;
248 }
250 public Result getWSDL(String suggestedFilename) {
251 File f = toFile(suggestedFilename);
252 wsdlFileName[0] = f;
253 return toResult(f);
254 }
255 public Result getSchemaOutput(String namespace, String suggestedFilename) {
256 if (namespace == null)
257 return null;
258 File f = toFile(suggestedFilename);
259 schemaFiles.put(namespace,f);
260 return toResult(f);
261 }
262 public Result getAbstractWSDL(Holder<String> filename) {
263 return toResult(toFile(filename.value));
264 }
265 public Result getSchemaOutput(String namespace, Holder<String> filename) {
266 return getSchemaOutput(namespace, filename.value);
267 }
268 // TODO pass correct impl's class name
269 });
271 wsdlGenInfo.setContainer(container);
272 wsdlGenInfo.setExtensions(ServiceFinder.find(WSDLGeneratorExtension.class).toArray());
273 wsdlGenInfo.setInlineSchemas(options.inlineSchemas);
274 rt.generateWSDL(wsdlGenInfo);
277 if(options.wsgenReport!=null)
278 generateWsgenReport(endpointClass,(AbstractSEIModelImpl)rt.getModel(),wsdlFileName[0],schemaFiles);
279 }
280 return true;
281 }
283 /**
284 * Generates a small XML file that captures the key activity of wsgen,
285 * so that test harness can pick up artifacts.
286 */
287 private void generateWsgenReport(Class<?> endpointClass, AbstractSEIModelImpl rtModel, File wsdlFile, Map<String,File> schemaFiles) {
288 try {
289 ReportOutput.Report report = TXW.create(ReportOutput.Report.class,
290 new StreamSerializer(new BufferedOutputStream(new FileOutputStream(options.wsgenReport))));
292 report.wsdl(wsdlFile.getAbsolutePath());
293 ReportOutput.writeQName(rtModel.getServiceQName(), report.service());
294 ReportOutput.writeQName(rtModel.getPortName(), report.port());
295 ReportOutput.writeQName(rtModel.getPortTypeName(), report.portType());
297 report.implClass(endpointClass.getName());
299 for (Map.Entry<String,File> e : schemaFiles.entrySet()) {
300 ReportOutput.Schema s = report.schema();
301 s.ns(e.getKey());
302 s.location(e.getValue().getAbsolutePath());
303 }
305 report.commit();
306 } catch (IOException e) {
307 // this is code for the test, so we can be lousy in the error handling
308 throw new Error(e);
309 }
310 }
312 /**
313 * "Namespace" for code needed to generate the report file.
314 */
315 static class ReportOutput {
316 @XmlElement("report")
317 interface Report extends TypedXmlWriter {
318 @XmlElement
319 void wsdl(String file); // location of WSDL
320 @XmlElement
321 QualifiedName portType();
322 @XmlElement
323 QualifiedName service();
324 @XmlElement
325 QualifiedName port();
327 /**
328 * Name of the class that has {@link javax.jws.WebService}.
329 */
330 @XmlElement
331 void implClass(String name);
333 @XmlElement
334 Schema schema();
335 }
337 interface QualifiedName extends TypedXmlWriter {
338 @XmlAttribute
339 void uri(String ns);
340 @XmlAttribute
341 void localName(String localName);
342 }
344 interface Schema extends TypedXmlWriter {
345 @XmlAttribute
346 void ns(String ns);
347 @XmlAttribute
348 void location(String filePath);
349 }
351 private static void writeQName( QName n, QualifiedName w ) {
352 w.uri(n.getNamespaceURI());
353 w.localName(n.getLocalPart());
354 }
355 }
357 protected void usage(WsgenOptions options) {
358 // Just don't see any point in passing WsgenOptions
359 // BadCommandLineException also shouldn't have options
360 if (options == null)
361 options = this.options;
362 System.out.println(WscompileMessages.WSGEN_HELP("WSGEN", options.protocols, options.nonstdProtocols.keySet()));
363 System.out.println(WscompileMessages.WSGEN_USAGE_EXAMPLES());
364 }
366 class Listener extends WsimportListener {
367 ConsoleErrorReporter cer = new ConsoleErrorReporter(out == null ? new PrintStream(new NullStream()) : out);
369 @Override
370 public void generatedFile(String fileName) {
371 message(fileName);
372 }
374 @Override
375 public void message(String msg) {
376 out.println(msg);
377 }
379 @Override
380 public void error(SAXParseException exception) {
381 cer.error(exception);
382 }
384 @Override
385 public void fatalError(SAXParseException exception) {
386 cer.fatalError(exception);
387 }
389 @Override
390 public void warning(SAXParseException exception) {
391 cer.warning(exception);
392 }
394 @Override
395 public void info(SAXParseException exception) {
396 cer.info(exception);
397 }
398 }
399 }