001: /*
002: Copyright (c) 2004-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.IOException;
032: import java.io.OutputStream;
033: import java.util.Iterator;
034: import java.util.Map;
035: import java.util.Set;
036:
037: import org.jibx.runtime.BindingDirectory;
038: import org.jibx.runtime.IBindingFactory;
039: import org.jibx.runtime.IMarshallable;
040: import org.jibx.runtime.IMarshaller;
041: import org.jibx.runtime.IMarshallingContext;
042: import org.jibx.runtime.IXMLWriter;
043: import org.jibx.runtime.JiBXException;
044: import org.jibx.runtime.impl.MarshallingContext;
045: import org.jibx.schema.elements.SchemaElement;
046: import org.jibx.util.StringIntSizedMap;
047:
048: /**
049: * WSDL writer class. This handles writing generated WSDLs and schemas.
050: *
051: * @author Dennis M. Sosnoski
052: */
053: public class WsdlWriter {
054: /** Fixed URI for WSDL namespace. */
055: public static final String WSDL_NAMESPACE_URI = "http://schemas.xmlsoap.org/wsdl/";
056:
057: /** Fixed prefix for WSDL namespace. */
058: public static final String WSDL_NAMESPACE_PREFIX = "wsdl";
059:
060: /** Fixed URI for SOAP namespace. */
061: public static final String SOAP_NAMESPACE_URI = "http://schemas.xmlsoap.org/wsdl/soap/";
062:
063: /** Fixed prefix for SOAP namespace. */
064: public static final String SOAP_NAMESPACE_PREFIX = "soap";
065:
066: /** Fixed prefix for WSDL target namespace. */
067: public static final String DEFINITIONS_NAMESPACE_PREFIX = "wns";
068:
069: /** Namespaces defined in binding. */
070: private StringIntSizedMap s_namespaceMap;
071:
072: /** Index of definitions class in binding. */
073: private int s_definitionsIndex;
074:
075: /** Namespace index for the WSDL namespace. */
076: private int s_wsdlNamespaceIndex;
077:
078: /** Map from extra namespace URIs to prefixes. */
079: private Map m_uriPrefixMap;
080:
081: /** Namespace index for the SOAP namespace. */
082: private int s_soapNamespaceIndex;
083:
084: /** Marshalling context. */
085: private final MarshallingContext m_marshalContext;
086:
087: /**
088: * Constructor.
089: *
090: * @throws JiBXException on error creating marshaller
091: */
092: public WsdlWriter() throws JiBXException {
093:
094: // set the marshalling contexts
095: IBindingFactory ifact = BindingDirectory
096: .getFactory(Definitions.class);
097: m_marshalContext = (MarshallingContext) ifact
098: .createMarshallingContext();
099:
100: // initialize namespace URI to index map
101: String[] nss = ifact.getNamespaces();
102: s_namespaceMap = new StringIntSizedMap(nss.length);
103: for (int i = 0; i < nss.length; i++) {
104: s_namespaceMap.add(nss[i], i);
105: }
106:
107: // create other statics used in code
108: s_wsdlNamespaceIndex = s_namespaceMap.get(WSDL_NAMESPACE_URI);
109: s_soapNamespaceIndex = s_namespaceMap.get(SOAP_NAMESPACE_URI);
110:
111: // find the index for the root object in WSDL
112: String[] classes = ifact.getMappedClasses();
113: s_definitionsIndex = -1;
114: String cname = Definitions.class.getName();
115: for (int i = 0; i < classes.length; i++) {
116: if (cname.equals(classes[i])) {
117: s_definitionsIndex = i;
118: break;
119: }
120: }
121: if (s_definitionsIndex < 0) {
122: throw new JiBXException("Missing binding definition for "
123: + cname);
124: }
125: }
126:
127: /**
128: * Write WSDL for service to output stream.
129: *
130: * @param def WSDL definitions information
131: * @param os destination output stream
132: * @exception JiBXException on error creating WSDL output
133: */
134: public void writeWSDL(Definitions def, OutputStream os)
135: throws JiBXException {
136:
137: // configure context for output stream
138: m_marshalContext.setOutput(os, null);
139: m_marshalContext.setIndent(2);
140: m_marshalContext.setUserContext(def);
141:
142: // set up information for namespace indexes and prefixes
143: Set uriset = def.getNamespaces();
144: String[] uris = new String[uriset.size()];
145: int[] indexes = new int[uris.length + 2];
146: String[] prefs = new String[uris.length + 2];
147: IXMLWriter writer = m_marshalContext.getXmlWriter();
148: int base = writer.getNamespaceCount();
149: int index = 0;
150: for (Iterator iter = uriset.iterator(); iter.hasNext();) {
151: String uri = (String) iter.next();
152: uris[index] = uri;
153: indexes[index] = base + index;
154: prefs[index++] = def.getPrefix(uri);
155: }
156: indexes[index] = s_wsdlNamespaceIndex;
157: prefs[index++] = WSDL_NAMESPACE_PREFIX;
158: indexes[index] = s_soapNamespaceIndex;
159: prefs[index] = SOAP_NAMESPACE_PREFIX;
160:
161: // add the namespace declarations to current element
162: writer.pushExtensionNamespaces(uris);
163: /* writer.openNamespaces(indexes, prefs);
164: for (int i = 0; i < uris.length; i++) {
165: String prefix = prefs[i];
166: String name = prefix.length() > 0 ?
167: "xmlns:" + prefix : "xmlns";
168: writer.addAttribute(0, name, uris[i]);
169: } */
170:
171: // write start tag with added namespaces
172: m_marshalContext.startTagNamespaces(s_wsdlNamespaceIndex,
173: "definitions", indexes, prefs);
174: m_marshalContext.attribute(0, "targetNamespace", def
175: .getWsdlNamespace());
176: m_marshalContext.closeStartContent();
177:
178: // marshal out remaining data
179: IMarshaller mar = m_marshalContext.getMarshaller(
180: s_definitionsIndex, Definitions.class.getName());
181: mar.marshal(def, m_marshalContext);
182:
183: // finish with close tag
184: m_marshalContext.endTag(s_wsdlNamespaceIndex, "definitions");
185: m_marshalContext.endDocument();
186: }
187:
188: /**
189: * Serialize a reference to a name defined in the WSDL. This generates the
190: * name text with the prefix (if any) used for the WSDL target namespace.
191: *
192: * @param name base name
193: * @param ictx
194: * @return qualified name with WSDL definitions prefix
195: */
196: public static String WsdlPrefixSerializer(String name,
197: IMarshallingContext ictx) {
198: Definitions def = (Definitions) ictx.getUserContext();
199: return def.getWsdlPrefix() + ':' + name;
200: }
201:
202: public static class SchemaMarshaller implements IMarshaller {
203: /** Marshalling context for schema. */
204: private final MarshallingContext m_schemaContext;
205:
206: public SchemaMarshaller() throws JiBXException {
207: IBindingFactory ifact = BindingDirectory
208: .getFactory(SchemaElement.class);
209: m_schemaContext = (MarshallingContext) ifact
210: .createMarshallingContext();
211: }
212:
213: public boolean isExtension(int index) {
214: return false;
215: }
216:
217: public void marshal(Object obj, IMarshallingContext ctx)
218: throws JiBXException {
219: try {
220: m_schemaContext
221: .setFromContext((MarshallingContext) ctx);
222: ((IMarshallable) obj).marshal(m_schemaContext);
223: m_schemaContext.getXmlWriter().flush();
224: } catch (IOException e) {
225: throw new JiBXException("Error writing schema", e);
226: }
227: }
228: }
229: }
|