001: /*
002: * Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package com.sun.tools.internal.ws.processor.modeler.wsdl;
026:
027: import static com.sun.tools.internal.ws.processor.modeler.wsdl.WSDLModelerBase.*;
028: import com.sun.tools.internal.ws.processor.config.ModelInfo;
029: import com.sun.tools.internal.ws.processor.modeler.wsdl.WSDLModelerBase.ProcessSOAPOperationInfo;
030: import com.sun.tools.internal.ws.wsdl.document.schema.SchemaKinds;
031: import com.sun.tools.internal.ws.wsdl.framework.Extensible;
032: import com.sun.tools.internal.ws.wsdl.framework.NoSuchEntityException;
033:
034: import org.xml.sax.InputSource;
035:
036: import javax.xml.namespace.QName;
037: import java.io.StringReader;
038: import java.io.StringWriter;
039: import java.text.MessageFormat;
040: import java.util.ArrayList;
041: import java.util.HashMap;
042: import java.util.HashSet;
043: import java.util.Iterator;
044: import java.util.List;
045: import java.util.Set;
046:
047: import com.sun.tools.internal.ws.wsdl.document.MessagePart;
048: import com.sun.tools.internal.ws.wsdl.document.Operation;
049: import com.sun.tools.internal.ws.wsdl.document.Kinds;
050: import com.sun.tools.internal.ws.wsdl.document.Message;
051: import com.sun.tools.internal.ws.wsdl.document.PortType;
052: import com.sun.tools.internal.ws.wsdl.document.Port;
053: import com.sun.tools.internal.ws.wsdl.document.Service;
054: import com.sun.tools.internal.ws.wsdl.document.WSDLDocument;
055: import com.sun.tools.internal.ws.wsdl.document.Binding;
056: import com.sun.tools.internal.ws.wsdl.document.BindingOperation;
057: import com.sun.tools.internal.ws.wsdl.document.jaxws.JAXWSBinding;
058: import com.sun.tools.internal.ws.wsdl.document.soap.*;
059:
060: /**
061: * @author Vivek Pandey
062: *
063: * Builds all possible pseudo schemas for async operation ResponseBean to feed to XJC.
064: */
065: public class PseudoSchemaBuilder {
066:
067: private final StringWriter buf = new StringWriter();
068: private final WSDLDocument wsdlDocument;
069: private final ModelInfo modelInfo;
070: private WSDLModeler wsdlModeler;
071: private final List<InputSource> schemas = new ArrayList<InputSource>();
072: private final HashMap<QName, Port> bindingNameToPortMap = new HashMap<QName, Port>();
073:
074: public static List<InputSource> build(WSDLModeler wsdlModeler,
075: ModelInfo modelInfo) {
076: PseudoSchemaBuilder b = new PseudoSchemaBuilder(
077: wsdlModeler.document, modelInfo);
078: b.wsdlModeler = wsdlModeler;
079: JAXBModelBuilder analyzer = wsdlModeler.getJAXBModelBuilder();
080: b.build();
081: for (int i = 0; i < b.schemas.size(); i++) {
082: InputSource is = b.schemas.get(i);
083: is.setSystemId("http://dummy.pseudo-schema#schema"
084: + (i + 1));
085: }
086: return b.schemas;
087: }
088:
089: private PseudoSchemaBuilder(WSDLDocument _wsdl, ModelInfo _modelInfo) {
090: this .wsdlDocument = _wsdl;
091: this .modelInfo = _modelInfo;
092: }
093:
094: private void build() {
095: for (Iterator<Service> itr = wsdlDocument.getDefinitions()
096: .services(); itr.hasNext();)
097: build(itr.next());
098: }
099:
100: private void build(Service service) {
101: for (Iterator<Port> itr = service.ports(); itr.hasNext();)
102: build(itr.next());
103: }
104:
105: private void build(Port port) {
106: if (wsdlModeler.isProvider(port))
107: return;
108: Binding binding = port.resolveBinding(wsdlDocument);
109:
110: SOAPBinding soapBinding = (SOAPBinding) getExtensionOfType(
111: binding, SOAPBinding.class);
112: //lets try and see if its SOAP 1.2. dont worry about extension flag, its
113: // handled much earlier
114: if (soapBinding == null) {
115: soapBinding = (SOAPBinding) getExtensionOfType(binding,
116: SOAP12Binding.class);
117: }
118: if (soapBinding == null)
119: return;
120: PortType portType = binding.resolvePortType(wsdlDocument);
121:
122: QName bindingName = WSDLModelerBase.getQNameOf(binding);
123:
124: //we dont want to process the port bound to the binding processed earlier
125: if (bindingNameToPortMap.containsKey(bindingName))
126: return;
127:
128: bindingNameToPortMap.put(bindingName, port);
129:
130: for (Iterator itr = binding.operations(); itr.hasNext();) {
131: BindingOperation bindingOperation = (BindingOperation) itr
132: .next();
133: SOAPOperation soapOperation = (SOAPOperation) getExtensionOfType(
134: bindingOperation, SOAPOperation.class);
135:
136: // get only the bounded operations
137: Set boundedOps = portType
138: .getOperationsNamed(bindingOperation.getName());
139: if (boundedOps.size() != 1)
140: continue;
141: Operation operation = (Operation) boundedOps.iterator()
142: .next();
143:
144: // No pseudo schema required for doc/lit
145: SOAPStyle bindingStyle = soapBinding.getStyle();
146: SOAPStyle operationStyle = (soapOperation != null) ? soapOperation
147: .getStyle()
148: : bindingStyle;
149: if (wsdlModeler.isAsync(portType, operation)) {
150: buildAsync(portType, operation, bindingOperation);
151: }
152: }
153: }
154:
155: /**
156: * @param portType
157: * @param operation
158: * @param bindingOperation
159: */
160: private void buildAsync(PortType portType, Operation operation,
161: BindingOperation bindingOperation) {
162: String operationName = getCustomizedOperationName(operation);//operation.getName();
163: if (operationName == null)
164: return;
165: Message outputMessage = null;
166: if (operation.getOutput() != null)
167: outputMessage = operation.getOutput().resolveMessage(
168: wsdlDocument);
169: if (outputMessage != null) {
170: List<MessagePart> allParts = new ArrayList<MessagePart>(
171: outputMessage.getParts());
172: if (allParts.size() > 1)
173: build(getOperationName(portType, operationName,
174: bindingOperation.getOutput()), allParts);
175: }
176:
177: }
178:
179: private String getCustomizedOperationName(Operation operation) {
180: JAXWSBinding jaxwsCustomization = (JAXWSBinding) getExtensionOfType(
181: operation, JAXWSBinding.class);
182: String operationName = (jaxwsCustomization != null) ? ((jaxwsCustomization
183: .getMethodName() != null) ? jaxwsCustomization
184: .getMethodName().getName() : null)
185: : null;
186: if (operationName != null) {
187: if (wsdlModeler.getEnvironment().getNames()
188: .isJavaReservedWord(operationName)) {
189: return null;
190: }
191:
192: return operationName;
193: }
194: return operation.getName();
195: }
196:
197: private void writeImports(QName elementName, List<MessagePart> parts) {
198: Set<String> uris = new HashSet<String>();
199: for (MessagePart p : parts) {
200: String ns = p.getDescriptor().getNamespaceURI();
201: if (!uris.contains(ns)
202: && !ns.equals("http://www.w3.org/2001/XMLSchema")
203: && !ns.equals(elementName.getNamespaceURI())) {
204: print("<xs:import namespace=''{0}''/>", ns);
205: uris.add(ns);
206: }
207: }
208: }
209:
210: boolean asyncRespBeanBinding = false;
211:
212: private void build(QName elementName, List<MessagePart> allParts) {
213:
214: print("<xs:schema xmlns:xs=''http://www.w3.org/2001/XMLSchema''"
215: + " xmlns:jaxb=''http://java.sun.com/xml/ns/jaxb''"
216: + " xmlns:xjc=''http://java.sun.com/xml/ns/jaxb/xjc''"
217: + " jaxb:extensionBindingPrefixes=''xjc''"
218: + " jaxb:version=''1.0''");
219: if ((elementName != null)
220: && elementName.getNamespaceURI().length() > 0) {
221: print(" targetNamespace=''{0}''>", elementName
222: .getNamespaceURI());
223: } else {
224: print(" >");
225: }
226:
227: writeImports(elementName, allParts);
228:
229: if (!asyncRespBeanBinding) {
230: print("<xs:annotation><xs:appinfo>"
231: + " <jaxb:schemaBindings>"
232: + " <jaxb:package name=''{0}'' />"
233: + " </jaxb:schemaBindings>"
234: + "</xs:appinfo></xs:annotation>", wsdlModeler
235: .getJavaPackage());
236: asyncRespBeanBinding = true;
237: }
238:
239: print("<xs:element name=''{0}''>", elementName.getLocalPart());
240: print("<xs:complexType>");
241: print("<xs:sequence>");
242:
243: for (MessagePart p : allParts) {
244: //rpclit wsdl:part must reference schema type not element, also it must exclude headers and mime parts
245: if (p.getDescriptorKind() == SchemaKinds.XSD_ELEMENT) {
246: print(
247: "<xs:element ref=''types:{0}'' xmlns:types=''{1}''/>",
248: p.getDescriptor().getLocalPart(), p
249: .getDescriptor().getNamespaceURI());
250: } else {
251: print(
252: "<xs:element name=''{0}'' type=''{1}'' xmlns=''{2}'' />",
253: p.getName(), p.getDescriptor().getLocalPart(),
254: p.getDescriptor().getNamespaceURI());
255: }
256: }
257:
258: print("</xs:sequence>");
259: print("</xs:complexType>");
260: print("</xs:element>");
261: print("</xs:schema>");
262:
263: // reset the StringWriter, so that next operation element could be written
264: if (buf.toString().length() > 0) {
265: // System.out.println("Response bean Schema for operation========> "+ elementName+"\n\n"+buf);
266: InputSource is = new InputSource(new StringReader(buf
267: .toString()));
268: schemas.add(is);
269: buf.getBuffer().setLength(0);
270: }
271: }
272:
273: private QName getOperationName(PortType portType,
274: String operationName, Extensible binding) {
275: if (operationName == null)
276: return null;
277: // String namespaceURI = wsdlDocument.getDefinitions().getTargetNamespaceURI()+"?"+portType.getName()+"?" + operationName;
278: String namespaceURI = "";
279: return new QName(namespaceURI, operationName + "Response");
280: }
281:
282: private void print(String msg) {
283: print(msg, new Object[0]);
284: }
285:
286: private void print(String msg, Object arg1) {
287: print(msg, new Object[] { arg1 });
288: }
289:
290: private void print(String msg, Object arg1, Object arg2) {
291: print(msg, new Object[] { arg1, arg2 });
292: }
293:
294: private void print(String msg, Object arg1, Object arg2, Object arg3) {
295: print(msg, new Object[] { arg1, arg2, arg3 });
296: }
297:
298: private void print(String msg, Object[] args) {
299: buf.write(MessageFormat.format(msg, args));
300: buf.write('\n');
301: }
302:
303: private static final Set<QName> nspaceToPackageSchema = new HashSet<QName>();
304: private static int schemaCounter;
305: }
|