src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsgenTool.java

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 1997, 2013, 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 */
25
26 package com.sun.tools.internal.ws.wscompile;
27
28 import com.oracle.webservices.internal.api.databinding.WSDLResolver;
29 import com.sun.istack.internal.tools.ParallelWorldClassLoader;
30 import com.sun.tools.internal.ws.ToolVersion;
31 import com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceAp;
32 import com.sun.tools.internal.ws.processor.modeler.wsdl.ConsoleErrorReporter;
33 import com.sun.tools.internal.ws.resources.WscompileMessages;
34 import com.sun.tools.internal.xjc.util.NullStream;
35 import com.sun.xml.internal.txw2.TXW;
36 import com.sun.xml.internal.txw2.TypedXmlWriter;
37 import com.sun.xml.internal.txw2.annotation.XmlAttribute;
38 import com.sun.xml.internal.txw2.annotation.XmlElement;
39 import com.sun.xml.internal.txw2.output.StreamSerializer;
40 import com.sun.xml.internal.ws.api.BindingID;
41 import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
42 import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
43 import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo;
44 import com.sun.xml.internal.ws.api.server.Container;
45 import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension;
46 import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
47 import com.sun.xml.internal.ws.model.ExternalMetadataReader;
48 import com.sun.xml.internal.ws.model.AbstractSEIModelImpl;
49 import com.sun.xml.internal.ws.util.ServiceFinder;
50 import org.xml.sax.SAXParseException;
51
52 import javax.tools.DiagnosticCollector;
53 import javax.tools.JavaCompiler;
54 import javax.tools.JavaFileObject;
55 import javax.tools.StandardJavaFileManager;
56 import javax.tools.ToolProvider;
57 import javax.xml.bind.annotation.XmlSeeAlso;
58 import javax.xml.namespace.QName;
59 import javax.xml.transform.Result;
60 import javax.xml.transform.stream.StreamResult;
61 import javax.xml.ws.EndpointReference;
62 import javax.xml.ws.Holder;
63 import java.io.BufferedOutputStream;
64 import java.io.File;
65 import java.io.FileNotFoundException;
66 import java.io.FileOutputStream;
67 import java.io.IOException;
68 import java.io.OutputStream;
69 import java.io.PrintStream;
70 import java.net.URLClassLoader;
71 import java.util.ArrayList;
72 import java.util.Collection;
73 import java.util.Collections;
74 import java.util.HashMap;
75 import java.util.List;
76 import java.util.Map;
77
78 /**
79 * @author Vivek Pandey
80 */
81
82 /*
83 * All annotation types are supported.
84 */
85 public class WsgenTool {
86 private final PrintStream out;
87 private final WsgenOptions options = new WsgenOptions();
88
89
90 public WsgenTool(OutputStream out, Container container) {
91 this.out = (out instanceof PrintStream) ? (PrintStream) out : new PrintStream(out);
92 this.container = container;
93 }
94
95
96 public WsgenTool(OutputStream out) {
97 this(out, null);
98 }
99
100 public boolean run(String[] args) {
101 final Listener listener = new Listener();
102 for (String arg : args) {
103 if (arg.equals("-version")) {
104 listener.message(
105 WscompileMessages.WSGEN_VERSION(ToolVersion.VERSION.MAJOR_VERSION));
106 return true;
107 }
108 if (arg.equals("-fullversion")) {
109 listener.message(
110 WscompileMessages.WSGEN_FULLVERSION(ToolVersion.VERSION.toString()));
111 return true;
112 }
113 }
114 try {
115 options.parseArguments(args);
116 options.validate();
117 if (!buildModel(options.endpoint.getName(), listener)) {
118 return false;
119 }
120 } catch (Options.WeAreDone done) {
121 usage(done.getOptions());
122 } catch (BadCommandLineException e) {
123 if (e.getMessage() != null) {
124 System.out.println(e.getMessage());
125 System.out.println();
126 }
127 usage(e.getOptions());
128 return false;
129 } catch (AbortException e) {
130 //error might have been reported
131 } finally {
132 if (!options.keep) {
133 options.removeGeneratedFiles();
134 }
135 }
136 return true;
137 }
138
139 private final Container container;
140
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 }
152
153 /**
154 *
155 * @param endpoint
156 * @param listener
157 * @return
158 * @throws BadCommandLineException
159 */
160 public boolean buildModel(String endpoint, Listener listener) throws BadCommandLineException {
161 final ErrorReceiverFilter errReceiver = new ErrorReceiverFilter(listener);
162
163 boolean bootCP = useBootClasspath(EndpointReference.class) || useBootClasspath(XmlSeeAlso.class);
164 List<String> args = new ArrayList<String>(6 + (bootCP ? 1 : 0) + (options.nocompile ? 1 : 0)
165 + (options.encoding != null ? 2 : 0));
166 args.add("-d");
167 args.add(options.destDir.getAbsolutePath());
168 args.add("-classpath");
169 args.add(options.classpath);
170 args.add("-s");
171 args.add(options.sourceDir.getAbsolutePath());
172 if (options.nocompile) {
173 args.add("-proc:only");
174 }
175 if (options.encoding != null) {
176 args.add("-encoding");
177 args.add(options.encoding);
178 }
179 if (bootCP) {
180 args.add(new StringBuilder()
181 .append("-Xbootclasspath/p:")
182 .append(JavaCompilerHelper.getJarFile(EndpointReference.class))
183 .append(File.pathSeparator)
184 .append(JavaCompilerHelper.getJarFile(XmlSeeAlso.class)).toString());
185 }
186 if (options.javacOptions != null) {
187 args.addAll(options.getJavacOptions(args, listener));
188 }
189
190 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();// compiler = JavacTool.create();
191 DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
192 StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
193 JavaCompiler.CompilationTask task = compiler.getTask(
194 null,
195 fileManager,
196 diagnostics,
197 args,
198 Collections.singleton(endpoint.replaceAll("\\$", ".")),
199 null);
200 task.setProcessors(Collections.singleton(new WebServiceAp(options, out)));
201 boolean result = task.call();
202
203 if (!result) {
204 out.println(WscompileMessages.WSCOMPILE_ERROR(WscompileMessages.WSCOMPILE_COMPILATION_FAILED()));
205 return false;
206 }
207 if (options.genWsdl) {
208 DatabindingConfig config = new DatabindingConfig();
209
210 List<String> externalMetadataFileNames = options.externalMetadataFiles;
211 boolean disableXmlSecurity = options.disableXmlSecurity;
212 if (externalMetadataFileNames != null && externalMetadataFileNames.size() > 0) {
213 config.setMetadataReader(new ExternalMetadataReader(getExternalFiles(externalMetadataFileNames), null, null, true, disableXmlSecurity));
214 }
215
216 String tmpPath = options.destDir.getAbsolutePath() + File.pathSeparator + options.classpath;
217 ClassLoader classLoader = new URLClassLoader(Options.pathToURLs(tmpPath),
218 this.getClass().getClassLoader());
219 Class<?> endpointClass;
220 try {
221 endpointClass = classLoader.loadClass(endpoint);
222 } catch (ClassNotFoundException e) {
223 throw new BadCommandLineException(WscompileMessages.WSGEN_CLASS_NOT_FOUND(endpoint));
224 }
225
226 BindingID bindingID = options.getBindingID(options.protocol);
227 if (!options.protocolSet) {
228 bindingID = BindingID.parse(endpointClass);
229 }
230 WebServiceFeatureList wsfeatures = new WebServiceFeatureList(endpointClass);
231 // RuntimeModeler rtModeler = new RuntimeModeler(endpointClass, options.serviceName, bindingID, wsfeatures.toArray());
232 // rtModeler.setClassLoader(classLoader);
233 if (options.portName != null)
234 config.getMappingInfo().setPortName(options.portName);//rtModeler.setPortName(options.portName);
235 // AbstractSEIModelImpl rtModel = rtModeler.buildRuntimeModel();
236
237 DatabindingFactory fac = DatabindingFactory.newInstance();
238 config.setEndpointClass(endpointClass);
239 config.getMappingInfo().setServiceName(options.serviceName);
240 config.setFeatures(wsfeatures.toArray());
241 config.setClassLoader(classLoader);
242 config.getMappingInfo().setBindingID(bindingID);
243 com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl) fac.createRuntime(config);
244
245 final File[] wsdlFileName = new File[1]; // used to capture the generated WSDL file.
246 final Map<String, File> schemaFiles = new HashMap<String, File>();
247
248 WSDLGenInfo wsdlGenInfo = new WSDLGenInfo();
249 wsdlGenInfo.setSecureXmlProcessingDisabled(disableXmlSecurity);
250
251 wsdlGenInfo.setWsdlResolver(
252 new WSDLResolver() {
253 private File toFile(String suggestedFilename) {
254 return new File(options.nonclassDestDir, suggestedFilename);
255 }
256
257 private Result toResult(File file) {
258 Result result;
259 try {
260 result = new StreamResult(new FileOutputStream(file));
261 result.setSystemId(file.getPath().replace('\\', '/'));
262 } catch (FileNotFoundException e) {
263 errReceiver.error(e);
264 return null;
265 }
266 return result;
267 }
268
269 @Override
270 public Result getWSDL(String suggestedFilename) {
271 File f = toFile(suggestedFilename);
272 wsdlFileName[0] = f;
273 return toResult(f);
274 }
275
276 public Result getSchemaOutput(String namespace, String suggestedFilename) {
277 if (namespace == null)
278 return null;
279 File f = toFile(suggestedFilename);
280 schemaFiles.put(namespace, f);
281 return toResult(f);
282 }
283
284 @Override
285 public Result getAbstractWSDL(Holder<String> filename) {
286 return toResult(toFile(filename.value));
287 }
288
289 @Override
290 public Result getSchemaOutput(String namespace, Holder<String> filename) {
291 return getSchemaOutput(namespace, filename.value);
292 }
293 // TODO pass correct impl's class name
294 });
295
296 wsdlGenInfo.setContainer(container);
297 wsdlGenInfo.setExtensions(ServiceFinder.find(WSDLGeneratorExtension.class).toArray());
298 wsdlGenInfo.setInlineSchemas(options.inlineSchemas);
299 rt.generateWSDL(wsdlGenInfo);
300
301
302 if (options.wsgenReport != null)
303 generateWsgenReport(endpointClass, (AbstractSEIModelImpl) rt.getModel(), wsdlFileName[0], schemaFiles);
304 }
305 return true;
306 }
307
308 private List<File> getExternalFiles(List<String> exts) {
309 List<File> files = new ArrayList<File>();
310 for (String ext : exts) {
311 // first try absolute path ...
312 File file = new File(ext);
313 if (!file.exists()) {
314 // then relative path ...
315 file = new File(options.sourceDir.getAbsolutePath() + File.separator + ext);
316 }
317 files.add(file);
318 }
319 return files;
320 }
321
322 /**
323 * Generates a small XML file that captures the key activity of wsgen,
324 * so that test harness can pick up artifacts.
325 */
326 private void generateWsgenReport(Class<?> endpointClass, AbstractSEIModelImpl rtModel, File wsdlFile, Map<String, File> schemaFiles) {
327 try {
328 ReportOutput.Report report = TXW.create(ReportOutput.Report.class,
329 new StreamSerializer(new BufferedOutputStream(new FileOutputStream(options.wsgenReport))));
330
331 report.wsdl(wsdlFile.getAbsolutePath());
332 ReportOutput.writeQName(rtModel.getServiceQName(), report.service());
333 ReportOutput.writeQName(rtModel.getPortName(), report.port());
334 ReportOutput.writeQName(rtModel.getPortTypeName(), report.portType());
335
336 report.implClass(endpointClass.getName());
337
338 for (Map.Entry<String, File> e : schemaFiles.entrySet()) {
339 ReportOutput.Schema s = report.schema();
340 s.ns(e.getKey());
341 s.location(e.getValue().getAbsolutePath());
342 }
343
344 report.commit();
345 } catch (IOException e) {
346 // this is code for the test, so we can be lousy in the error handling
347 throw new Error(e);
348 }
349 }
350
351 /**
352 * "Namespace" for code needed to generate the report file.
353 */
354 static class ReportOutput {
355 @XmlElement("report")
356 interface Report extends TypedXmlWriter {
357 @XmlElement
358 void wsdl(String file); // location of WSDL
359
360 @XmlElement
361 QualifiedName portType();
362
363 @XmlElement
364 QualifiedName service();
365
366 @XmlElement
367 QualifiedName port();
368
369 /**
370 * Name of the class that has {@link javax.jws.WebService}.
371 */
372 @XmlElement
373 void implClass(String name);
374
375 @XmlElement
376 Schema schema();
377 }
378
379 interface QualifiedName extends TypedXmlWriter {
380 @XmlAttribute
381 void uri(String ns);
382
383 @XmlAttribute
384 void localName(String localName);
385 }
386
387 interface Schema extends TypedXmlWriter {
388 @XmlAttribute
389 void ns(String ns);
390
391 @XmlAttribute
392 void location(String filePath);
393 }
394
395 private static void writeQName(QName n, QualifiedName w) {
396 w.uri(n.getNamespaceURI());
397 w.localName(n.getLocalPart());
398 }
399 }
400
401 protected void usage(Options options) {
402 // Just don't see any point in passing WsgenOptions
403 // BadCommandLineException also shouldn't have options
404 if (options == null)
405 options = this.options;
406 if (options instanceof WsgenOptions) {
407 System.out.println(WscompileMessages.WSGEN_HELP("WSGEN",
408 ((WsgenOptions)options).protocols,
409 ((WsgenOptions)options).nonstdProtocols.keySet()));
410 System.out.println(WscompileMessages.WSGEN_USAGE_EXTENSIONS());
411 System.out.println(WscompileMessages.WSGEN_USAGE_EXAMPLES());
412 }
413 }
414
415 class Listener extends WsimportListener {
416 ConsoleErrorReporter cer = new ConsoleErrorReporter(out == null ? new PrintStream(new NullStream()) : out);
417
418 @Override
419 public void generatedFile(String fileName) {
420 message(fileName);
421 }
422
423 @Override
424 public void message(String msg) {
425 out.println(msg);
426 }
427
428 @Override
429 public void error(SAXParseException exception) {
430 cer.error(exception);
431 }
432
433 @Override
434 public void fatalError(SAXParseException exception) {
435 cer.fatalError(exception);
436 }
437
438 @Override
439 public void warning(SAXParseException exception) {
440 cer.warning(exception);
441 }
442
443 @Override
444 public void info(SAXParseException exception) {
445 cer.info(exception);
446 }
447 }
448 }

mercurial