001: /*
002: Copyright (c) 2007, Dennis M. Sosnoski.
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: package org.jibx.ws.wsdl;
030:
031: import java.io.File;
032: import java.io.FileOutputStream;
033: import java.io.IOException;
034: import java.net.URL;
035: import java.util.ArrayList;
036: import java.util.HashMap;
037: import java.util.Iterator;
038: import java.util.List;
039: import java.util.Map;
040: import java.util.Set;
041:
042: import org.jibx.binding.generator.BindingGenerator;
043: import org.jibx.binding.generator.BindingHolder;
044: import org.jibx.binding.generator.ClassCustom;
045: import org.jibx.binding.generator.CustomBase;
046: import org.jibx.binding.generator.GlobalCustom;
047: import org.jibx.binding.generator.SchemaGenerator;
048: import org.jibx.binding.generator.SchemaHolder;
049: import org.jibx.binding.generator.SchemaMappingDetail;
050: import org.jibx.binding.model.BindingElement;
051: import org.jibx.binding.model.CollectionElement;
052: import org.jibx.binding.model.DocumentFormatter;
053: import org.jibx.binding.model.IClass;
054: import org.jibx.binding.model.IClassLocator;
055: import org.jibx.binding.model.MappingElement;
056: import org.jibx.binding.model.ValidationContext;
057: import org.jibx.binding.model.ValidationProblem;
058: import org.jibx.runtime.BindingDirectory;
059: import org.jibx.runtime.IBindingFactory;
060: import org.jibx.runtime.IMarshallable;
061: import org.jibx.runtime.IMarshallingContext;
062: import org.jibx.runtime.JiBXException;
063: import org.jibx.runtime.QName;
064: import org.jibx.schema.IComponent;
065: import org.jibx.schema.elements.AnnotationElement;
066: import org.jibx.schema.elements.ComplexTypeElement;
067: import org.jibx.schema.elements.DocumentationElement;
068: import org.jibx.schema.elements.ElementElement;
069: import org.jibx.schema.elements.SchemaElement;
070: import org.jibx.schema.elements.SequenceElement;
071: import org.jibx.schema.types.Count;
072: import org.jibx.util.InsertionOrderedSet;
073: import org.jibx.util.Types;
074: import org.w3c.dom.Node;
075:
076: /**
077: * Start-from-code WSDL generator using JiBX data binding. This starts from one
078: * or more service classes, each with one or more methods to be exposed as
079: * service operations, and generates complete bindings and WSDL for the
080: * services.
081: *
082: * @author Dennis M. Sosnoski
083: */
084: public class Jibx2Wsdl {
085: /** Customizations information. */
086: private final GlobalCustom m_global;
087:
088: /** WSDL customizations. */
089: private final WsdlCustom m_wsdlCustom;
090:
091: /** Binding generator. */
092: private final BindingGenerator m_bindingGenerator;
093:
094: /** Schema generator. */
095: private final SchemaGenerator m_schemaGenerator;
096:
097: /** Map from schema namespace URIs to schema holders. */
098: private final Map m_uriSchemaMap;
099:
100: /** Map from fully qualified class name to schema type name. */
101: private Map m_classTypeMap;
102:
103: /** Locator for class information (<code>null</code> if none). */
104: private final IClassLocator m_locator;
105:
106: /** Document used for annotations (<code>null</code> if none). */
107: private final DocumentFormatter m_formatter;
108:
109: /**
110: * Constructor.
111: *
112: * @param loc class locator
113: * @param global customizations information
114: * @param wsdl WSDL customizations information
115: */
116: private Jibx2Wsdl(IClassLocator loc, GlobalCustom global,
117: WsdlCustom wsdl) {
118: m_locator = loc;
119: m_global = global;
120: m_bindingGenerator = new BindingGenerator(global);
121: m_schemaGenerator = new SchemaGenerator(loc, global);
122: m_uriSchemaMap = new HashMap();
123: m_formatter = new DocumentFormatter();
124: m_wsdlCustom = wsdl;
125: }
126:
127: /**
128: * Get the qualified name used for an abstract mapping. This throws an
129: * exception if the qualified name is not found.
130: *
131: * @param type
132: * @param mapping
133: * @return qualified name
134: */
135: private QName getMappingQName(String type, MappingElement mapping) {
136: SchemaMappingDetail detail = m_schemaGenerator
137: .getMappingDetail(mapping);
138: if (detail == null) {
139: throw new IllegalStateException(
140: "No mapping found for type " + type);
141: } else if (detail.isType()) {
142: return detail.getTypeName();
143: } else {
144: throw new IllegalStateException(
145: "Need abstract mapping for type " + type);
146: }
147: }
148:
149: /**
150: * Build an element representing a parameter or return value.
151: *
152: * @param parm
153: * @param typemap map from parameterized type to abstract mapping name
154: * @return constructed element
155: */
156: private ElementElement buildValueElement(ValueCustom parm,
157: Map typemap) {
158:
159: // create the basic element definition
160: ElementElement elem = new ElementElement();
161: if (!parm.isRequired()) {
162: elem.setMinOccurs(Count.COUNT_ZERO);
163: }
164: String type = parm.getType();
165: if (type.endsWith("[]")) {
166: elem.setMaxOccurs(Count.COUNT_UNBOUNDED);
167: }
168:
169: // check type or reference for element
170: boolean isref = false;
171: String ptype = parm.getBoundType();
172: QName tname = (QName) typemap.get(ptype);
173: if (tname == null) {
174: tname = Types.schemaType(ptype);
175: if (tname == null) {
176: String usetype = ptype.endsWith(">") ? type : ptype;
177: BindingGenerator.MappingDetail detail = m_bindingGenerator
178: .getMappingDetail(usetype);
179: if (detail == null) {
180: throw new IllegalStateException(
181: "No mapping found for type " + usetype);
182: } else if (detail.isExtended()) {
183: elem.setRef(detail.getElementQName());
184: isref = true;
185: } else {
186: MappingElement mapping = detail
187: .getAbstractMapping();
188: tname = mapping.getTypeQName();
189: if (tname == null) {
190: tname = getMappingQName(usetype, mapping);
191: }
192: }
193: }
194: }
195: if (!isref) {
196:
197: // set element type and name
198: elem.setType(tname);
199: String ename = parm.getElementName();
200: if (ename == null) {
201: ename = tname.getName();
202: }
203: elem.setName(ename);
204: }
205:
206: // add documentation if available
207: List nodes = parm.getDocumentation();
208: if (nodes != null) {
209: AnnotationElement anno = new AnnotationElement();
210: DocumentationElement doc = new DocumentationElement();
211: for (Iterator iter = nodes.iterator(); iter.hasNext();) {
212: Node node = (Node) iter.next();
213: doc.addContent(node);
214: }
215: anno.getItemsList().add(doc);
216: elem.setAnnotation(anno);
217: }
218: return elem;
219: }
220:
221: /**
222: * Add reference defined by element to schema. This finds the namespace of
223: * the type or element reference used by the provided element, and adds that
224: * namespace to the schema references.
225: *
226: * @param elem
227: * @param holder
228: */
229: private void addSchemaReference(ElementElement elem,
230: SchemaHolder holder) {
231: QName qname = elem.getType();
232: if (qname == null) {
233: qname = elem.getRef();
234: }
235: if (qname != null) {
236: String rns = qname.getUri();
237: if (!holder.getNamespace().equals(rns)
238: && !IComponent.SCHEMA_NAMESPACE.equals(rns)) {
239: holder.addReference((SchemaHolder) m_uriSchemaMap
240: .get(rns));
241: }
242: }
243: }
244:
245: /**
246: * Build WSDL for service.
247: *
248: * @param service
249: * @param typemap map from parameterized type to abstract mapping name
250: * @return constructed WSDL definitions
251: */
252: private Definitions buildWSDL(ServiceCustom service, Map typemap) {
253:
254: // initialize root object of definition
255: String wns = service.getWsdlNamespace();
256: String sns = service.getNamespace();
257: String spfx = wns.equals(sns) ? "tns" : "sns";
258: Definitions def = new Definitions(service.getPortTypeName(),
259: service.getBindingName(), service.getServiceName(),
260: service.getPortName(), "tns", wns, spfx, sns);
261: def.setServiceLocation(service.getServiceAddress());
262:
263: // add service documentation if available
264: IClass info = m_locator.getClassInfo(service.getClassName());
265: if (info != null) {
266: List nodes = m_formatter.docToNodes(info.getJavaDoc());
267: def.setPortTypeDocumentation(nodes);
268: }
269:
270: // find or create the schema element and namespace
271: SchemaHolder holder = (SchemaHolder) m_uriSchemaMap.get(sns);
272: if (holder == null) {
273: holder = new SchemaHolder(sns);
274: }
275: SchemaElement schema = holder.getSchema();
276: def.getSchemas().add(schema);
277:
278: // process messages and operations used by service
279: ArrayList ops = service.getOperations();
280: Map fltmap = new HashMap();
281: for (int i = 0; i < ops.size(); i++) {
282:
283: // get information for operation
284: OperationCustom odef = (OperationCustom) ops.get(i);
285: String oname = odef.getOperationName();
286: Operation op = new Operation(oname);
287: op.setDocumentation(odef.getDocumentation());
288: op.setSoapAction(odef.getSoapAction());
289:
290: // generate input message information
291: QName qname = new QName(sns, odef.getRequestWrapperName());
292: MessagePart part = new MessagePart("part", qname);
293: Message msg = new Message(odef.getRequestMessageName(),
294: part);
295: op.addInputMessage(msg);
296: def.addMessage(msg);
297:
298: // add corresponding schema definition to schema
299: SequenceElement seq = new SequenceElement();
300: ArrayList parms = odef.getParameters();
301: for (int j = 0; j < parms.size(); j++) {
302: ValueCustom parm = (ValueCustom) parms.get(j);
303: ElementElement pelem = buildValueElement(parm, typemap);
304: seq.getParticleList().add(pelem);
305: addSchemaReference(pelem, holder);
306: }
307: ComplexTypeElement tdef = new ComplexTypeElement();
308: tdef.setContentDefinition(seq);
309: ElementElement elem = new ElementElement();
310: elem.setName(odef.getRequestWrapperName());
311: elem.setInlineType(tdef);
312: schema.getTopLevelChildren().add(elem);
313:
314: // generate output message information
315: qname = new QName(sns, odef.getResponseWrapperName());
316: part = new MessagePart("part", qname);
317: msg = new Message(odef.getResponseMessageName(), part);
318: op.addOutputMessage(msg);
319: def.addMessage(msg);
320:
321: // add corresponding schema definition to schema
322: seq = new SequenceElement();
323: ValueCustom ret = odef.getReturn();
324: if (!"void".equals(ret.getType())) {
325: ElementElement relem = buildValueElement(ret, typemap);
326: seq.getParticleList().add(relem);
327: addSchemaReference(relem, holder);
328: }
329: tdef = new ComplexTypeElement();
330: tdef.setContentDefinition(seq);
331: elem = new ElementElement();
332: elem.setName(odef.getResponseWrapperName());
333: elem.setInlineType(tdef);
334: schema.getTopLevelChildren().add(elem);
335:
336: // process fault message(s) for operation
337: ArrayList thrws = odef.getThrows();
338: for (int j = 0; j < thrws.size(); j++) {
339: ThrowsCustom thrw = (ThrowsCustom) thrws.get(j);
340: String type = thrw.getType();
341: msg = (Message) fltmap.get(type);
342: if (msg == null) {
343:
344: // first time for this throwable, create the message
345: FaultCustom fault = m_wsdlCustom
346: .forceFaultCustomization(type);
347: qname = new QName(sns, fault.getElementName());
348: part = new MessagePart("fault", qname);
349: msg = new Message(fault.getFaultName(), part);
350: def.addMessage(msg);
351:
352: // make sure the corresponding mapping exists
353: BindingGenerator.MappingDetail detail = m_bindingGenerator
354: .getMappingDetail(fault.getDataType());
355: if (detail == null) {
356: throw new IllegalStateException(
357: "No mapping found for type " + type);
358: }
359:
360: // record that the fault has been defined
361: fltmap.put(type, msg);
362: }
363:
364: // add fault to operation definition
365: op.addFaultMessage(msg);
366: }
367:
368: // add operation to list of definitions
369: def.addOperation(op);
370:
371: }
372: holder.fixReferences();
373: return def;
374: }
375:
376: /**
377: * Accumulate data type(s) from value to be included in binding.
378: *
379: * @param value
380: * @param dataset set of types for binding
381: */
382: private void accumulateData(ValueCustom value, Set dataset) {
383: String type = value.getBoundType();
384: if (!dataset.contains(type) && !Types.isSimpleValue(type)) {
385: String itype = value.getItemType();
386: if (itype == null) {
387: dataset.add(type);
388: } else {
389: dataset.add(itype);
390: }
391: }
392: }
393:
394: /**
395: * Add the <mapping> definition for a typed collection to a binding. This
396: * always creates an abstract mapping with the type name based on both the
397: * item type and the collection type.
398: *
399: * @param value collection value
400: * @param typemap map from parameterized type to abstract mapping name
401: * @param bind target binding
402: * @return qualified name for collection
403: */
404: public QName addCollectionBinding(ValueCustom value, Map typemap,
405: BindingHolder bind) {
406:
407: // check for existing mapping
408: String ptype = value.getBoundType();
409: QName qname = (QName) typemap.get(ptype);
410: if (qname == null) {
411:
412: // create abstract mapping for collection class type
413: MappingElement mapping = new MappingElement();
414: mapping.setClassName(value.getType());
415: mapping.setAbstract(true);
416: mapping.setCreateType(value.getCreateType());
417: mapping.setFactoryName(value.getFactoryMethod());
418:
419: // generate the mapping type name from item class name and suffix
420: String suffix;
421: String type = value.getType();
422: IClass clas = m_global.getClassInfo(type);
423: if (clas.isImplements("Ljava/util/List;")) {
424: suffix = "List";
425: } else if (clas.isImplements("Ljava/util/Set;")) {
426: suffix = "Set";
427: } else {
428: suffix = "Collection";
429: }
430: String itype = value.getItemType();
431: ClassCustom cust = m_global.forceClassCustomization(itype);
432:
433: // register the type name for mapping
434: String name = cust.getSimpleName() + suffix;
435: qname = new QName(bind.getNamespace(), CustomBase
436: .convertName(name, CustomBase.CAMEL_CASE_NAMES));
437: mapping.setTypeQName(qname);
438: typemap.put(ptype, qname);
439:
440: // add collection definition details
441: CollectionElement coll = new CollectionElement();
442: m_bindingGenerator.defineCollection(itype, value
443: .getItemElementName(), coll, bind);
444: mapping.addChild(coll);
445:
446: // add mapping to binding
447: bind.getBinding().addTopChild(mapping);
448: }
449: return qname;
450: }
451:
452: /**
453: * Generate based on list of service classes.
454: *
455: * @param classes service class list
456: * @param extras list of extra classes for binding
457: * @param name singleton or root binding definition file name
458: * @return list of WSDLs
459: * @throws JiBXException
460: * @throws IOException
461: */
462: private ArrayList generate(List classes, List extras, String name)
463: throws JiBXException, IOException {
464:
465: // add any service classes not already present in customizations
466: for (int i = 0; i < classes.size(); i++) {
467: String sclas = (String) classes.get(i);
468: if (m_wsdlCustom.getServiceCustomization(sclas) == null) {
469: m_wsdlCustom.addServiceCustomization(sclas);
470: }
471: }
472:
473: // accumulate the data classes used by all service operations
474: // TODO: throws class handling, with multiple services per WSDL
475: InsertionOrderedSet abstrs = new InsertionOrderedSet();
476: InsertionOrderedSet concrs = new InsertionOrderedSet();
477: ArrayList qnames = new ArrayList();
478: List services = m_wsdlCustom.getServices();
479: for (Iterator iter = services.iterator(); iter.hasNext();) {
480: ServiceCustom service = (ServiceCustom) iter.next();
481: List ops = service.getOperations();
482: for (Iterator iter1 = ops.iterator(); iter1.hasNext();) {
483: OperationCustom op = (OperationCustom) iter1.next();
484: List parms = op.getParameters();
485: for (Iterator iter2 = parms.iterator(); iter2.hasNext();) {
486: accumulateData((ValueCustom) iter2.next(), abstrs);
487: }
488: accumulateData(op.getReturn(), abstrs);
489: ArrayList thrws = op.getThrows();
490: for (int i = 0; i < thrws.size(); i++) {
491:
492: // add concrete mapping for data type, if used
493: ThrowsCustom thrw = (ThrowsCustom) thrws.get(i);
494: FaultCustom fault = m_wsdlCustom
495: .forceFaultCustomization(thrw.getType());
496: if (!concrs.contains(fault.getDataType())) {
497: concrs.add(fault.getDataType());
498: qnames.add(new QName(service.getNamespace(),
499: fault.getElementName()));
500: }
501: }
502: }
503: }
504:
505: // include extra classes as needing concrete mappings
506: for (int i = 0; i < extras.size(); i++) {
507: String type = (String) extras.get(i);
508: if (!concrs.contains(type)) {
509: concrs.add(type);
510: ClassCustom clas = m_global
511: .forceClassCustomization(type);
512: qnames.add(new QName(clas.getNamespace(), clas
513: .getElementName()));
514: }
515: }
516:
517: // generate bindings for all data classes used
518: m_bindingGenerator.generateSpecified(qnames, concrs.asList(),
519: abstrs.asList());
520:
521: // add binding definitions for collections passed or returned
522: Map typemap = new HashMap();
523: for (Iterator iter = services.iterator(); iter.hasNext();) {
524: ServiceCustom service = (ServiceCustom) iter.next();
525: List ops = service.getOperations();
526: BindingHolder hold = null;
527: String uri = service.getNamespace();
528: for (Iterator iter1 = ops.iterator(); iter1.hasNext();) {
529: OperationCustom op = (OperationCustom) iter1.next();
530: List parms = op.getParameters();
531: for (Iterator iter2 = parms.iterator(); iter2.hasNext();) {
532: ValueCustom parm = (ValueCustom) iter2.next();
533: if (parm.getItemType() != null) {
534: if (hold == null) {
535: hold = m_bindingGenerator.findBinding(uri);
536: }
537: addCollectionBinding(parm, typemap, hold);
538: }
539: }
540: ValueCustom ret = op.getReturn();
541: if (ret.getItemType() != null) {
542: if (hold == null) {
543: hold = m_bindingGenerator.findBinding(uri);
544: }
545: addCollectionBinding(ret, typemap, hold);
546: }
547: }
548: if (hold != null) {
549: hold.fixReferences();
550: }
551: }
552:
553: // get singleton or root binding with fake URL for locating includes
554: BindingHolder rhold = m_bindingGenerator
555: .configureBindings(name);
556: BindingElement binding = rhold.getBinding();
557: binding.setBaseUrl(new URL("http://localhost/"));
558:
559: // add all other binding definitions for access from root
560: ArrayList uris = m_bindingGenerator.getNamespaces();
561: ArrayList holders = new ArrayList();
562: for (int i = 0; i < uris.size(); i++) {
563: String uri = (String) uris.get(i);
564: BindingHolder hold = m_bindingGenerator.findBinding(uri);
565: holders.add(hold);
566: if (hold != rhold) {
567: String path = "http://localhost/" + hold.getFileName();
568: binding.addIncludeBinding(path, hold.getBinding());
569: }
570: }
571:
572: // validate the binding definition
573: ValidationContext vctx = new ValidationContext(m_locator);
574: vctx.setBindingRoot(binding);
575: binding.runValidation(vctx);
576:
577: // report any validation errors
578: ArrayList probs = vctx.getProblems();
579: if (vctx.getErrorCount() > 0 || vctx.getFatalCount() > 0) {
580: System.out.println("Errors in generated binding:");
581: for (int j = 0; j < probs.size(); j++) {
582: ValidationProblem prob = (ValidationProblem) probs
583: .get(j);
584: System.out
585: .print(prob.getSeverity() >= ValidationProblem.ERROR_LEVEL ? "Error: "
586: : "Warning: ");
587: System.out.println(prob.getDescription());
588: }
589:
590: // print all the bindings containing the errors
591: IBindingFactory fact = BindingDirectory
592: .getFactory(BindingElement.class);
593: IMarshallingContext ictx = fact.createMarshallingContext();
594: ictx.setOutput(System.out, null);
595: ictx.setIndent(2);
596: for (int i = 0; i < uris.size(); i++) {
597: String uri = (String) uris.get(i);
598: BindingHolder hold = m_bindingGenerator
599: .findBinding(uri);
600: ictx.reset();
601: ((IMarshallable) hold.getBinding()).marshal(ictx);
602: ictx.getXmlWriter().flush();
603: }
604: return null;
605:
606: } else {
607:
608: // build and record the schemas
609: ArrayList schemas = m_schemaGenerator.generate(holders);
610: // TODO: fix this
611: for (int i = 0; i < schemas.size(); i++) {
612: SchemaHolder holder = (SchemaHolder) schemas.get(i);
613: m_uriSchemaMap.put(holder.getNamespace(), holder);
614: }
615:
616: // build the WSDL for each service
617: ArrayList wsdls = new ArrayList();
618: for (Iterator iter = services.iterator(); iter.hasNext();) {
619: wsdls.add(buildWSDL((ServiceCustom) iter.next(),
620: typemap));
621: }
622: return wsdls;
623:
624: }
625: }
626:
627: /**
628: * Run the WSDL generation using command line parameters.
629: *
630: * @param args
631: * @throws JiBXException
632: * @throws IOException
633: */
634: public static void main(String[] args) throws JiBXException,
635: IOException {
636: WsdlGeneratorCommandLine parms = new WsdlGeneratorCommandLine();
637: if (args.length > 0 && parms.processArgs(args)) {
638:
639: // generate services, bindings, and WSDLs
640: Jibx2Wsdl inst = new Jibx2Wsdl(parms.getLocator(), parms
641: .getGlobal(), parms.getWsdlCustom());
642: ArrayList wsdls = inst.generate(parms.getExtraArgs(), parms
643: .getExtraTypes(), "binding.xml");
644: if (wsdls != null) {
645:
646: // write the bindings
647: inst.m_bindingGenerator.writeBindings(parms
648: .getGeneratePath());
649:
650: // write the corresponding schemas
651: IBindingFactory fact = BindingDirectory
652: .getFactory(SchemaElement.class);
653: for (Iterator iter = inst.m_uriSchemaMap.values()
654: .iterator(); iter.hasNext();) {
655: SchemaHolder holder = (SchemaHolder) iter.next();
656: IMarshallingContext ictx = fact
657: .createMarshallingContext();
658: File file = new File(parms.getGeneratePath(),
659: holder.getFileName());
660: ictx.setOutput(new FileOutputStream(file), null);
661: ictx.setIndent(2);
662: ((IMarshallable) holder.getSchema()).marshal(ictx);
663: ictx.getXmlWriter().flush();
664: }
665:
666: // output the generated WSDLs
667: WsdlWriter writer = new WsdlWriter();
668: for (int i = 0; i < wsdls.size(); i++) {
669: Definitions def = (Definitions) wsdls.get(i);
670: File file = new File(parms.getGeneratePath(), def
671: .getServiceName()
672: + ".wsdl");
673: writer.writeWSDL(def, new FileOutputStream(file));
674: }
675: }
676:
677: } else {
678: if (args.length > 0) {
679: System.err
680: .println("Terminating due to command line errors");
681: } else {
682: parms.printUsage();
683: }
684: System.exit(1);
685: }
686: }
687: }
|