001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.server;
038:
039: import com.sun.xml.ws.api.server.DocumentAddressResolver;
040: import com.sun.xml.ws.api.server.PortAddressResolver;
041: import com.sun.xml.ws.api.server.SDDocument;
042: import com.sun.xml.ws.api.server.SDDocumentFilter;
043: import com.sun.xml.ws.api.server.SDDocumentSource;
044: import com.sun.xml.ws.api.server.WSEndpoint;
045: import com.sun.xml.ws.api.streaming.XMLStreamWriterFactory;
046: import com.sun.xml.ws.streaming.XMLStreamReaderUtil;
047: import com.sun.xml.ws.wsdl.parser.ParserUtil;
048: import com.sun.xml.ws.wsdl.parser.WSDLConstants;
049: import com.sun.xml.ws.util.RuntimeVersion;
050:
051: import javax.xml.namespace.QName;
052: import javax.xml.stream.XMLInputFactory;
053: import javax.xml.stream.XMLStreamConstants;
054: import javax.xml.stream.XMLStreamException;
055: import javax.xml.stream.XMLStreamReader;
056: import javax.xml.stream.XMLStreamWriter;
057: import javax.xml.ws.WebServiceException;
058: import java.io.IOException;
059: import java.io.OutputStream;
060: import java.net.URL;
061: import java.util.HashSet;
062: import java.util.Set;
063:
064: /**
065: * {@link SDDocument} implmentation.
066: *
067: * <p>
068: * This extends from {@link SDDocumentSource} so that
069: * JAX-WS server runtime code can use {@link SDDocument}
070: * as {@link SDDocumentSource}.
071: *
072: * @author Kohsuke Kawaguchi
073: * @author Jitendra Kotamraju
074: */
075: class SDDocumentImpl extends SDDocumentSource implements SDDocument {
076:
077: private static final String NS_XSD = "http://www.w3.org/2001/XMLSchema";
078: private static final QName SCHEMA_INCLUDE_QNAME = new QName(NS_XSD,
079: "include");
080: private static final QName SCHEMA_IMPORT_QNAME = new QName(NS_XSD,
081: "import");
082: private static final QName SCHEMA_REDEFINE_QNAME = new QName(
083: NS_XSD, "redefine");
084: private static final String VERSION_COMMENT = " Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is "
085: + RuntimeVersion.VERSION + ". ";
086:
087: /**
088: * Creates {@link SDDocument} from {@link SDDocumentSource}.
089: * @param src WSDL document infoset
090: * @param serviceName wsdl:service name
091: * @param portTypeName
092: * The information about the port of {@link WSEndpoint} to which this document is built for.
093: * These values are used to determine which document is the concrete and abstract WSDLs
094: * for this endpoint.
095: *
096: * @return null
097: * Always non-null.
098: */
099: public static SDDocumentImpl create(SDDocumentSource src,
100: QName serviceName, QName portTypeName) {
101: URL systemId = src.getSystemId();
102:
103: try {
104: // RuntimeWSDLParser parser = new RuntimeWSDLParser(null);
105: XMLStreamReader reader = src.read();
106: try {
107: XMLStreamReaderUtil.nextElementContent(reader);
108:
109: QName rootName = reader.getName();
110: if (rootName.equals(WSDLConstants.QNAME_SCHEMA)) {
111: String tns = ParserUtil
112: .getMandatoryNonEmptyAttribute(reader,
113: WSDLConstants.ATTR_TNS);
114: Set<String> importedDocs = new HashSet<String>();
115: while (XMLStreamReaderUtil.nextContent(reader) != XMLStreamConstants.END_DOCUMENT) {
116: if (reader.getEventType() != XMLStreamConstants.START_ELEMENT)
117: continue;
118: QName name = reader.getName();
119: if (SCHEMA_INCLUDE_QNAME.equals(name)
120: || SCHEMA_IMPORT_QNAME.equals(name)
121: || SCHEMA_REDEFINE_QNAME.equals(name)) {
122: String importedDoc = reader
123: .getAttributeValue(null,
124: "schemaLocation");
125: if (importedDoc != null) {
126: importedDocs.add(new URL(src
127: .getSystemId(), importedDoc)
128: .toString());
129: }
130: }
131: }
132: return new SchemaImpl(rootName, systemId, src, tns,
133: importedDocs);
134: } else if (rootName
135: .equals(WSDLConstants.QNAME_DEFINITIONS)) {
136: String tns = ParserUtil
137: .getMandatoryNonEmptyAttribute(reader,
138: WSDLConstants.ATTR_TNS);
139:
140: boolean hasPortType = false;
141: boolean hasService = false;
142: Set<String> importedDocs = new HashSet<String>();
143:
144: // if WSDL, parse more
145: while (XMLStreamReaderUtil.nextContent(reader) != XMLStreamConstants.END_DOCUMENT) {
146: if (reader.getEventType() != XMLStreamConstants.START_ELEMENT)
147: continue;
148:
149: QName name = reader.getName();
150: if (WSDLConstants.QNAME_PORT_TYPE.equals(name)) {
151: String pn = ParserUtil
152: .getMandatoryNonEmptyAttribute(
153: reader,
154: WSDLConstants.ATTR_NAME);
155: if (portTypeName != null) {
156: if (portTypeName.getLocalPart().equals(
157: pn)
158: && portTypeName
159: .getNamespaceURI()
160: .equals(tns)) {
161: hasPortType = true;
162: }
163: }
164: } else if (WSDLConstants.QNAME_SERVICE
165: .equals(name)) {
166: String sn = ParserUtil
167: .getMandatoryNonEmptyAttribute(
168: reader,
169: WSDLConstants.ATTR_NAME);
170: QName sqn = new QName(tns, sn);
171: if (serviceName.equals(sqn)) {
172: hasService = true;
173: }
174: } else if (WSDLConstants.QNAME_IMPORT
175: .equals(name)) {
176: String importedDoc = reader
177: .getAttributeValue(null, "location");
178: if (importedDoc != null) {
179: importedDocs.add(new URL(src
180: .getSystemId(), importedDoc)
181: .toString());
182: }
183: } else if (SCHEMA_INCLUDE_QNAME.equals(name)
184: || SCHEMA_IMPORT_QNAME.equals(name)
185: || SCHEMA_REDEFINE_QNAME.equals(name)) {
186: String importedDoc = reader
187: .getAttributeValue(null,
188: "schemaLocation");
189: if (importedDoc != null) {
190: importedDocs.add(new URL(src
191: .getSystemId(), importedDoc)
192: .toString());
193: }
194: }
195: }
196: return new WSDLImpl(rootName, systemId, src, tns,
197: hasPortType, hasService, importedDocs);
198: } else {
199: return new SDDocumentImpl(rootName, systemId, src);
200: }
201: } finally {
202: reader.close();
203: }
204: } catch (WebServiceException e) {
205: throw new ServerRtException("runtime.parser.wsdl",
206: systemId, e);
207: } catch (IOException e) {
208: throw new ServerRtException("runtime.parser.wsdl",
209: systemId, e);
210: } catch (XMLStreamException e) {
211: throw new ServerRtException("runtime.parser.wsdl",
212: systemId, e);
213: }
214: }
215:
216: private final QName rootName;
217: private final SDDocumentSource source;
218:
219: /**
220: * Set when {@link ServiceDefinitionImpl} is constructed.
221: */
222: /*package*/ServiceDefinitionImpl owner;
223:
224: /**
225: * The original system ID of this document.
226: *
227: * When this document contains relative references to other resources,
228: * this field is used to find which {@link com.sun.xml.ws.server.SDDocumentImpl} it refers to.
229: *
230: * Must not be null.
231: */
232: private final URL url;
233: private final Set<String> imports;
234:
235: protected SDDocumentImpl(QName rootName, URL url,
236: SDDocumentSource source) {
237: this (rootName, url, source, new HashSet<String>());
238: }
239:
240: protected SDDocumentImpl(QName rootName, URL url,
241: SDDocumentSource source, Set<String> imports) {
242: assert url != null;
243: this .rootName = rootName;
244: this .source = source;
245: this .url = url;
246: this .imports = imports;
247: }
248:
249: public QName getRootName() {
250: return rootName;
251: }
252:
253: public boolean isWSDL() {
254: return false;
255: }
256:
257: public boolean isSchema() {
258: return false;
259: }
260:
261: public URL getURL() {
262: return url;
263: }
264:
265: public XMLStreamReader read(XMLInputFactory xif)
266: throws IOException, XMLStreamException {
267: return source.read(xif);
268: }
269:
270: public XMLStreamReader read() throws IOException,
271: XMLStreamException {
272: return source.read();
273: }
274:
275: public URL getSystemId() {
276: return url;
277: }
278:
279: public Set<String> getImports() {
280: return imports;
281: }
282:
283: public void writeTo(PortAddressResolver portAddressResolver,
284: DocumentAddressResolver resolver, OutputStream os)
285: throws IOException {
286: XMLStreamWriter w = null;
287: try {
288: //generate the WSDL with utf-8 encoding and XML version 1.0
289: w = XMLStreamWriterFactory.create(os, "UTF-8");
290: w.writeStartDocument("UTF-8", "1.0");
291: writeTo(portAddressResolver, resolver, w);
292: w.writeEndDocument();
293: } catch (XMLStreamException e) {
294: IOException ioe = new IOException(e.getMessage());
295: ioe.initCause(e);
296: throw ioe;
297: } finally {
298: try {
299: if (w != null)
300: w.close();
301: } catch (XMLStreamException e) {
302: IOException ioe = new IOException(e.getMessage());
303: ioe.initCause(e);
304: throw ioe;
305: }
306: }
307: }
308:
309: public void writeTo(PortAddressResolver portAddressResolver,
310: DocumentAddressResolver resolver, XMLStreamWriter out)
311: throws XMLStreamException, IOException {
312: for (SDDocumentFilter f : owner.filters) {
313: out = f.filter(this , out);
314: }
315:
316: XMLStreamReader xsr = source.read();
317: try {
318: out.writeComment(VERSION_COMMENT);
319: new WSDLPatcher(owner.owner, this , portAddressResolver,
320: resolver).bridge(xsr, out);
321: } finally {
322: xsr.close();
323: }
324: }
325:
326: /**
327: * {@link SDDocument.Schema} implementation.
328: *
329: * @author Kohsuke Kawaguchi
330: */
331: private static final class SchemaImpl extends SDDocumentImpl
332: implements SDDocument.Schema {
333: private final String targetNamespace;
334:
335: public SchemaImpl(QName rootName, URL url,
336: SDDocumentSource source, String targetNamespace,
337: Set<String> imports) {
338: super (rootName, url, source, imports);
339: this .targetNamespace = targetNamespace;
340: }
341:
342: public String getTargetNamespace() {
343: return targetNamespace;
344: }
345:
346: public boolean isSchema() {
347: return true;
348: }
349: }
350:
351: private static final class WSDLImpl extends SDDocumentImpl
352: implements SDDocument.WSDL {
353: private final String targetNamespace;
354: private final boolean hasPortType;
355: private final boolean hasService;
356:
357: public WSDLImpl(QName rootName, URL url,
358: SDDocumentSource source, String targetNamespace,
359: boolean hasPortType, boolean hasService,
360: Set<String> imports) {
361: super (rootName, url, source, imports);
362: this .targetNamespace = targetNamespace;
363: this .hasPortType = hasPortType;
364: this .hasService = hasService;
365: }
366:
367: public String getTargetNamespace() {
368: return targetNamespace;
369: }
370:
371: public boolean hasPortType() {
372: return hasPortType;
373: }
374:
375: public boolean hasService() {
376: return hasService;
377: }
378:
379: public boolean isWSDL() {
380: return true;
381: }
382: }
383:
384: }
|