001: /*
002: * Copyright (c) 1998-2007 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.soap.wsdl;
030:
031: import java.io.*;
032:
033: import java.util.ArrayList;
034: import java.util.HashMap;
035: import java.util.List;
036: import java.util.Map;
037:
038: import javax.xml.bind.JAXBException;
039: import javax.xml.bind.Unmarshaller;
040:
041: import javax.xml.bind.annotation.XmlAccessType;
042: import javax.xml.bind.annotation.XmlAccessorType;
043: import javax.xml.bind.annotation.XmlAttribute;
044: import javax.xml.bind.annotation.XmlElement;
045: import javax.xml.bind.annotation.XmlElements;
046: import javax.xml.bind.annotation.XmlRootElement;
047: import javax.xml.bind.annotation.XmlTransient;
048:
049: import javax.xml.namespace.QName;
050:
051: import static com.caucho.soap.wsdl.WSDLConstants.*;
052:
053: import com.caucho.java.JavaWriter;
054: import com.caucho.util.L10N;
055: import com.caucho.vfs.Vfs;
056: import com.caucho.vfs.WriteStream;
057:
058: import com.caucho.xml.schema.Type;
059:
060: /**
061: * WSDL Definitions top level
062: */
063: @XmlAccessorType(XmlAccessType.FIELD)
064: @XmlRootElement(name="definitions",namespace=WSDL_NAMESPACE)
065: public class WSDLDefinitions extends WSDLExtensibleDocumented {
066: @XmlTransient
067: private static final L10N L = new L10N(WSDLDefinitions.class);
068:
069: @XmlAttribute(name="name")
070: private String _name;
071:
072: @XmlAttribute(name="targetNamespace")
073: private String _targetNamespace;
074:
075: @XmlElement(name="import",namespace=WSDL_NAMESPACE)
076: private List<WSDLImport> _imports;
077:
078: @XmlElement(name="types",namespace=WSDL_NAMESPACE,required=true)
079: private List<WSDLTypes> _types;
080:
081: @XmlElement(name="message",namespace=WSDL_NAMESPACE,required=true)
082: private List<WSDLMessage> _messages;
083:
084: @XmlElement(name="portType",namespace=WSDL_NAMESPACE,required=true)
085: private List<WSDLPortType> _portTypes;
086:
087: @XmlElement(name="binding",namespace=WSDL_NAMESPACE,required=true)
088: private List<WSDLBinding> _bindings;
089:
090: @XmlElement(name="service",namespace=WSDL_NAMESPACE,required=true)
091: private List<WSDLService> _services;
092:
093: @XmlTransient
094: private final Map<QName, WSDLMessage> _messageMap = new HashMap<QName, WSDLMessage>();
095:
096: @XmlTransient
097: private final Map<QName, WSDLPortType> _portTypeMap = new HashMap<QName, WSDLPortType>();
098:
099: @XmlTransient
100: private final Map<QName, WSDLBinding> _bindingMap = new HashMap<QName, WSDLBinding>();
101:
102: @XmlTransient
103: private String _endpointAddress;
104:
105: @XmlTransient
106: private String _bindingId;
107:
108: /**
109: * Sets the definition name.
110: */
111: public void setName(String name) {
112: _name = name;
113: }
114:
115: public String getName() {
116: return _name;
117: }
118:
119: /**
120: * Sets the target namespace
121: */
122: public void setTargetNamespace(String uri) {
123: _targetNamespace = uri;
124: }
125:
126: /**
127: * Gets the target namespace
128: */
129: public String getTargetNamespace() {
130: return _targetNamespace;
131: }
132:
133: public List<WSDLImport> getImports() {
134: if (_imports == null)
135: return _imports = new ArrayList<WSDLImport>();
136:
137: return _imports;
138: }
139:
140: public List<WSDLTypes> getTypes() {
141: if (_types == null)
142: return _types = new ArrayList<WSDLTypes>();
143:
144: return _types;
145: }
146:
147: public List<WSDLMessage> getMessages() {
148: if (_messages == null)
149: return _messages = new ArrayList<WSDLMessage>();
150:
151: return _messages;
152: }
153:
154: public List<WSDLPortType> getPortTypes() {
155: if (_portTypes == null)
156: return _portTypes = new ArrayList<WSDLPortType>();
157:
158: return _portTypes;
159: }
160:
161: public List<WSDLBinding> getBindings() {
162: if (_bindings == null)
163: return _bindings = new ArrayList<WSDLBinding>();
164:
165: return _bindings;
166: }
167:
168: public List<WSDLService> getServices() {
169: if (_services == null)
170: return _services = new ArrayList<WSDLService>();
171:
172: return _services;
173: }
174:
175: public String getBindingId(QName serviceName, QName portName) {
176: if (_bindingId == null) {
177: if (!serviceName.getNamespaceURI().equals(
178: getTargetNamespace()))
179: return null;
180:
181: // first find out which binding we're looking for
182: QName bindingName = null;
183:
184: if (_services != null) {
185: for (int i = 0; i < _services.size(); i++) {
186: WSDLService service = _services.get(i);
187:
188: if (serviceName.getLocalPart().equals(
189: service.getName())) {
190: List<WSDLPort> ports = service.getPorts();
191:
192: for (int j = 0; j < ports.size(); j++) {
193: WSDLPort port = ports.get(j);
194:
195: if (portName.getLocalPart().equals(
196: port.getName())) {
197: bindingName = port.getBinding();
198: break;
199: }
200: }
201:
202: if (bindingName != null)
203: break;
204: }
205: }
206: }
207:
208: if (bindingName != null && _bindings != null) {
209: for (int i = 0; i < _bindings.size(); i++) {
210: WSDLBinding binding = _bindings.get(i);
211:
212: if (bindingName.getLocalPart().equals(
213: binding.getName())) {
214: List<Object> any = binding.getAny();
215:
216: for (int j = 0; j < any.size(); j++) {
217: if (any.get(j) instanceof SOAPBinding) {
218: SOAPBinding soapBinding = (SOAPBinding) any
219: .get(j);
220:
221: _bindingId = soapBinding.getTransport();
222:
223: return _bindingId;
224: }
225: }
226: }
227: }
228: }
229: }
230:
231: return _bindingId;
232: }
233:
234: public String getEndpointAddress(QName serviceName, QName portName) {
235: if (_endpointAddress == null) {
236: if (!serviceName.getNamespaceURI().equals(
237: getTargetNamespace()))
238: return null;
239:
240: // dig down to find the <soap:address location="..."/>
241: if (_services != null) {
242: for (int i = 0; i < _services.size(); i++) {
243: WSDLService service = _services.get(i);
244:
245: if (serviceName.getLocalPart().equals(
246: service.getName())) {
247: List<WSDLPort> ports = service.getPorts();
248:
249: for (int j = 0; j < ports.size(); j++) {
250: WSDLPort port = ports.get(j);
251:
252: if (portName.getLocalPart().equals(
253: port.getName())) {
254: List<Object> any = port.getAny();
255:
256: for (int k = 0; k < any.size(); k++) {
257: if (any.get(k) instanceof SOAPAddress) {
258: SOAPAddress address = (SOAPAddress) any
259: .get(k);
260:
261: _endpointAddress = address
262: .getLocation();
263:
264: return _endpointAddress;
265: }
266: }
267: }
268: }
269: }
270: }
271: }
272: }
273:
274: return _endpointAddress;
275: }
276:
277: /**
278: * Sets up the cached, transient data.
279: **/
280: public void afterUnmarshal(Unmarshaller u, Object o)
281: throws JAXBException, WSDLValidationException {
282: if (_messages != null) {
283: for (WSDLMessage message : _messages) {
284: QName name = null;
285:
286: if (_targetNamespace != null)
287: name = new QName(_targetNamespace, message
288: .getName());
289: else
290: name = new QName(message.getName());
291:
292: _messageMap.put(name, message);
293: }
294: }
295:
296: if (_portTypes != null) {
297: for (WSDLPortType portType : _portTypes) {
298: QName name = null;
299:
300: if (_targetNamespace != null)
301: name = new QName(_targetNamespace, portType
302: .getName());
303: else
304: name = new QName(portType.getName());
305:
306: _portTypeMap.put(name, portType);
307: }
308: }
309:
310: if (_bindings != null) {
311: for (WSDLBinding binding : _bindings) {
312: QName name = null;
313:
314: if (_targetNamespace != null)
315: name = new QName(_targetNamespace, binding
316: .getName());
317: else
318: name = new QName(binding.getName());
319:
320: _bindingMap.put(name, binding);
321: }
322: }
323:
324: resolveImports(u);
325:
326: for (WSDLMessage message : getMessages()) {
327: for (WSDLPart part : message.getParts()) {
328: Type type = getType(part.getElement());
329:
330: if (type == null)
331: throw new WSDLValidationException(
332: L
333: .l(
334: "Element type {0} for part {1} of message {2} is not defined in this WSDL's schema",
335: part.getElement(), part
336: .getName(), message
337: .getName()));
338:
339: part.setType(type);
340: }
341: }
342:
343: // check that all the messages referenced by operations are defined
344: for (WSDLPortType portType : getPortTypes()) {
345: portType.setDefinitions(this );
346:
347: for (WSDLOperation operation : portType.getOperations()) {
348: operation.setPortType(portType);
349:
350: for (WSDLOperationInput input : operation.getInputs()) {
351: WSDLMessage message = getMessage(input
352: .getMessageName());
353:
354: if (message == null)
355: throw new WSDLValidationException(
356: L
357: .l(
358: "Input message {0} for operation {1} is not defined in this WSDL",
359: input.getMessageName(),
360: operation.getName()));
361:
362: input.setMessage(message);
363: }
364:
365: for (WSDLOperationOutput output : operation
366: .getOutputs()) {
367: WSDLMessage message = getMessage(output
368: .getMessageName());
369:
370: if (message == null)
371: throw new WSDLValidationException(
372: L
373: .l(
374: "Output message {0} for operation {1} is not defined in this WSDL",
375: output.getMessageName(),
376: operation.getName()));
377:
378: output.setMessage(message);
379: }
380:
381: for (WSDLOperationFault fault : operation.getFaults()) {
382: WSDLMessage message = getMessage(fault
383: .getMessageName());
384:
385: if (message == null)
386: throw new WSDLValidationException(
387: L
388: .l(
389: "Fault message {0} for operation {1} is not defined in this WSDL",
390: fault.getMessageName(),
391: operation.getName()));
392:
393: fault.setMessage(message);
394: }
395: }
396: }
397:
398: // assign the binding to a portType and check that all
399: // the operations are defined
400: for (WSDLBinding binding : getBindings()) {
401: WSDLPortType portType = getPortType(binding.getType());
402:
403: if (portType == null)
404: throw new WSDLValidationException(
405: L
406: .l(
407: "PortType {0} for binding {1} is not defined in this WSDL",
408: binding.getType(), binding
409: .getName()));
410:
411: binding.setPortType(portType);
412:
413: for (WSDLBindingOperation bindingOp : binding
414: .getOperations()) {
415: WSDLOperation operation = portType
416: .getOperation(bindingOp.getName());
417:
418: if (operation == null)
419: throw new WSDLValidationException(
420: L
421: .l(
422: "PortType {0} has no operation {1} for binding {2}",
423: portType.getName(),
424: bindingOp.getName(),
425: binding.getName()));
426:
427: bindingOp.setOperation(operation);
428: }
429: }
430: }
431:
432: public WSDLMessage getMessage(QName name) {
433: return _messageMap.get(name);
434: }
435:
436: public WSDLPortType getPortType(QName name) {
437: return _portTypeMap.get(name);
438: }
439:
440: public WSDLBinding getBinding(QName name) {
441: return _bindingMap.get(name);
442: }
443:
444: public Type getType(QName typeName) {
445: if (_types == null)
446: return null;
447:
448: for (int i = 0; i < _types.size(); i++) {
449: WSDLTypes types = _types.get(i);
450:
451: Type type = types.getType(typeName);
452:
453: if (type != null)
454: return type;
455: }
456:
457: return null;
458: }
459:
460: public void resolveImports(Unmarshaller u) throws JAXBException {
461: if (_types == null)
462: return;
463:
464: for (int i = 0; i < _types.size(); i++) {
465: WSDLTypes types = _types.get(i);
466: types.resolveImports(u);
467: }
468: }
469:
470: public void writeJAXBClasses(File outputDirectory, String pkg)
471: throws IOException {
472: if (_types == null)
473: return;
474:
475: for (int i = 0; i < _types.size(); i++) {
476: WSDLTypes types = _types.get(i);
477: types.writeJAXBClasses(outputDirectory, pkg);
478: }
479: }
480:
481: public void generateJava(Unmarshaller u, File sourceDir,
482: File classDir, String pkg) throws WSDLValidationException,
483: JAXBException, IOException {
484: for (WSDLService service : getServices()) {
485: for (WSDLPort port : service.getPorts()) {
486: WSDLBinding binding = getBinding(port.getBinding());
487:
488: if (binding == null)
489: throw new WSDLValidationException(
490: L
491: .l(
492: "Binding {0} for port {1} not defined in this WSDL",
493: port.getBinding(), port
494: .getName()));
495:
496: WSDLPortType portType = binding.getPortType();
497:
498: File dir = new File(sourceDir, pkg.replace(".",
499: File.separator));
500:
501: dir.mkdirs();
502:
503: File output = new File(dir, portType.getName()
504: + ".java");
505: WriteStream os = null;
506:
507: try {
508: os = Vfs.openWrite(output.toString());
509: JavaWriter out = new JavaWriter(os);
510:
511: out.println("package " + pkg + ";");
512: out.println();
513: out.println("import java.math.BigDecimal;");
514: out.println("import java.math.BigInteger;");
515: out.println("import java.util.List;");
516: out.println("import javax.jws.WebMethod;");
517: out.println("import javax.jws.WebParam;");
518: out.println("import javax.jws.WebResult;");
519: out.println("import javax.jws.WebService;");
520: out
521: .println("import javax.xml.datatype.XMLGregorianCalendar;");
522: out.println("import javax.xml.ws.RequestWrapper;");
523: out.println("import javax.xml.ws.ResponseWrapper;");
524: out.println();
525: out.print("@WebService(name=\""
526: + portType.getName() + "\",");
527: out.println("targetNamespace=\""
528: + getTargetNamespace() + "\")");
529: out.println("public interface "
530: + portType.getName() + "{");
531:
532: out.pushDepth();
533:
534: for (WSDLBindingOperation bindingOp : binding
535: .getOperations()) {
536: bindingOp.generateJava(out);
537: out.println();
538: out.println();
539: }
540:
541: out.popDepth();
542:
543: out.println("}");
544: } finally {
545: if (os != null)
546: os.close();
547: }
548:
549: output = new File(dir, portType.getName()
550: + "Service.java");
551: os = null;
552:
553: try {
554: os = Vfs.openWrite(output.toString());
555: JavaWriter out = new JavaWriter(os);
556:
557: out.println("package " + pkg + ";");
558: out.println();
559: out.println("import java.net.URL;");
560: out.println("import javax.xml.namespace.QName;");
561: out.println("import javax.xml.ws.Service;");
562: out.println();
563: out.println("public class " + portType.getName()
564: + "Service");
565: out.println(" extends Service");
566: out.println("{");
567:
568: out.pushDepth();
569:
570: out.print("public " + portType.getName()
571: + "Service");
572: out
573: .println("(URL wsdlDocumentLocation, QName serviceName)");
574: out.println("{");
575: out.pushDepth();
576: out
577: .println("super(wsdlDocumentLocation, serviceName);");
578: out.popDepth();
579: out.println("}");
580:
581: out.popDepth();
582:
583: out.println("}");
584: } finally {
585: if (os != null)
586: os.close();
587: }
588:
589: }
590: }
591:
592: writeJAXBClasses(sourceDir, pkg);
593:
594: File dir = new File(sourceDir, pkg.replace(".", File.separator));
595: File[] sources = dir.listFiles(new FilenameFilter() {
596: public boolean accept(File dir, String name) {
597: return name.endsWith(".java");
598: }
599: });
600:
601: if (sources.length == 0) {
602: // XXX Warning message?
603: System.out
604: .println(" No sources found in " + dir + "!!!!!!");
605: return;
606: }
607:
608: com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main();
609:
610: String[] args = new String[2 + sources.length];
611:
612: args[0] = "-d";
613: args[1] = classDir.getAbsolutePath();
614:
615: for (int i = 0; i < sources.length; i++)
616: args[i + 2] = sources[i].getAbsolutePath();
617:
618: javac.compile(args);
619: }
620: }
|