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.istack.NotNull;
040: import com.sun.xml.stream.buffer.MutableXMLStreamBuffer;
041: import com.sun.xml.stream.buffer.XMLStreamBufferResult;
042: import com.sun.xml.ws.api.server.SDDocument;
043: import com.sun.xml.ws.api.server.SDDocumentSource;
044: import com.sun.xml.ws.wsdl.writer.WSDLResolver;
045:
046: import javax.xml.namespace.QName;
047: import javax.xml.transform.Result;
048: import javax.xml.ws.Holder;
049: import javax.xml.ws.WebServiceException;
050: import java.net.URL;
051: import java.net.MalformedURLException;
052: import java.util.ArrayList;
053: import java.util.HashMap;
054: import java.util.List;
055: import java.util.Map;
056:
057: /**
058: * WSDLGenerator uses WSDLResolver while creating WSDL artifacts. WSDLResolver
059: * is used to control the file names and which artifact to be generated or not.
060: *
061: * @author Jitendra Kotamraju
062: */
063: final class WSDLGenResolver implements WSDLResolver {
064:
065: private final List<SDDocumentImpl> docs;
066: private final List<SDDocumentSource> newDocs = new ArrayList<SDDocumentSource>();
067: private SDDocumentSource concreteWsdlSource;
068:
069: private SDDocumentImpl abstractWsdl;
070: private SDDocumentImpl concreteWsdl;
071:
072: /**
073: * targetNS -> schema documents.
074: */
075: private final Map<String, List<SDDocumentImpl>> nsMapping = new HashMap<String, List<SDDocumentImpl>>();
076:
077: private final QName serviceName;
078: private final QName portTypeName;
079:
080: public WSDLGenResolver(@NotNull
081: List<SDDocumentImpl> docs, QName serviceName, QName portTypeName) {
082: this .docs = docs;
083: this .serviceName = serviceName;
084: this .portTypeName = portTypeName;
085:
086: for (SDDocumentImpl doc : docs) {
087: if (doc.isWSDL()) {
088: SDDocument.WSDL wsdl = (SDDocument.WSDL) doc;
089: if (wsdl.hasPortType())
090: abstractWsdl = doc;
091: }
092: if (doc.isSchema()) {
093: SDDocument.Schema schema = (SDDocument.Schema) doc;
094: List<SDDocumentImpl> sysIds = nsMapping.get(schema
095: .getTargetNamespace());
096: if (sysIds == null) {
097: sysIds = new ArrayList<SDDocumentImpl>();
098: nsMapping.put(schema.getTargetNamespace(), sysIds);
099: }
100: sysIds.add(doc);
101: }
102: }
103: }
104:
105: /**
106: * Generates the concrete WSDL that contains service element.
107: *
108: * @return Result the generated concrete WSDL
109: */
110: public Result getWSDL(String filename) {
111: URL url = createURL(filename);
112: MutableXMLStreamBuffer xsb = new MutableXMLStreamBuffer();
113: xsb.setSystemId(url.toExternalForm());
114: concreteWsdlSource = SDDocumentSource.create(url, xsb);
115: newDocs.add(concreteWsdlSource);
116: XMLStreamBufferResult r = new XMLStreamBufferResult(xsb);
117: r.setSystemId(filename);
118: return r;
119: }
120:
121: /**
122: * At present, it returns file URL scheme eventhough there is no resource
123: * in the filesystem.
124: *
125: * @return URL of the generated document
126: *
127: */
128: private URL createURL(String filename) {
129: try {
130: return new URL("file:///" + filename);
131: } catch (MalformedURLException e) {
132: // TODO: I really don't think this is the right way to handle this error,
133: // WSDLResolver needs to be documented carefully.
134: throw new WebServiceException(e);
135: }
136: }
137:
138: /**
139: * Updates filename if the suggested filename need to be changed in
140: * wsdl:import. If the metadata already contains abstract wsdl(i.e. a WSDL
141: * which has the porttype), then the abstract wsdl shouldn't be generated
142: *
143: * return null if abstract WSDL need not be generated
144: * Result the abstract WSDL
145: */
146: public Result getAbstractWSDL(Holder<String> filename) {
147: if (abstractWsdl != null) {
148: filename.value = abstractWsdl.getURL().toString();
149: return null; // Don't generate abstract WSDL
150: }
151: URL url = createURL(filename.value);
152: MutableXMLStreamBuffer xsb = new MutableXMLStreamBuffer();
153: xsb.setSystemId(url.toExternalForm());
154: SDDocumentSource abstractWsdlSource = SDDocumentSource.create(
155: url, xsb);
156: newDocs.add(abstractWsdlSource);
157: XMLStreamBufferResult r = new XMLStreamBufferResult(xsb);
158: r.setSystemId(filename.value);
159: return r;
160: }
161:
162: /**
163: * Updates filename if the suggested filename need to be changed in
164: * xsd:import. If there is already a schema document for the namespace
165: * in the metadata, then it is not generated.
166: *
167: * return null if schema need not be generated
168: * Result the generated schema document
169: */
170: public Result getSchemaOutput(String namespace,
171: Holder<String> filename) {
172: List<SDDocumentImpl> schemas = nsMapping.get(namespace);
173: if (schemas != null) {
174: if (schemas.size() > 1) {
175: throw new ServerRtException("server.rt.err",
176: "More than one schema for the target namespace "
177: + namespace);
178: }
179: filename.value = schemas.get(0).getURL().toExternalForm();
180: return null; // Don't generate schema
181: }
182:
183: URL url = createURL(filename.value);
184: MutableXMLStreamBuffer xsb = new MutableXMLStreamBuffer();
185: xsb.setSystemId(url.toExternalForm());
186: SDDocumentSource sd = SDDocumentSource.create(url, xsb);
187: newDocs.add(sd);
188:
189: XMLStreamBufferResult r = new XMLStreamBufferResult(xsb);
190: r.setSystemId(filename.value);
191: return r;
192: }
193:
194: /**
195: * Converts SDDocumentSource to SDDocumentImpl and updates original docs. It
196: * categories the generated documents into WSDL, Schema types.
197: *
198: * @return the primary WSDL
199: * null if it is not there in the generated documents
200: *
201: */
202: public SDDocumentImpl updateDocs() {
203: for (SDDocumentSource doc : newDocs) {
204: SDDocumentImpl docImpl = SDDocumentImpl.create(doc,
205: serviceName, portTypeName);
206: if (doc == concreteWsdlSource) {
207: concreteWsdl = docImpl;
208: }
209: docs.add(docImpl);
210: }
211: return concreteWsdl;
212: }
213:
214: }
|