Thu, 31 Aug 2017 15:18:52 +0800
merge
1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.ws.wsdl.writer;
28 import com.sun.istack.internal.NotNull;
29 import com.sun.xml.internal.ws.api.server.PortAddressResolver;
30 import com.sun.xml.internal.ws.util.xml.XMLStreamReaderToXMLStreamWriter;
31 import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants;
32 import com.sun.xml.internal.ws.addressing.W3CAddressingConstants;
33 import com.sun.xml.internal.ws.addressing.v200408.MemberSubmissionAddressingConstants;
34 import com.sun.istack.internal.Nullable;
36 import javax.xml.namespace.QName;
37 import javax.xml.stream.XMLStreamException;
38 import java.util.logging.Logger;
40 /**
41 * Patches WSDL with the correct endpoint address and the relative paths
42 * to other documents.
43 *
44 * @author Jitendra Kotamraju
45 * @author Kohsuke Kawaguchi
46 */
47 public final class WSDLPatcher extends XMLStreamReaderToXMLStreamWriter {
49 private static final String NS_XSD = "http://www.w3.org/2001/XMLSchema";
50 private static final QName SCHEMA_INCLUDE_QNAME = new QName(NS_XSD, "include");
51 private static final QName SCHEMA_IMPORT_QNAME = new QName(NS_XSD, "import");
52 private static final QName SCHEMA_REDEFINE_QNAME = new QName(NS_XSD, "redefine");
54 private static final Logger logger = Logger.getLogger(
55 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".wsdl.patcher");
57 private final DocumentLocationResolver docResolver;
58 private final PortAddressResolver portAddressResolver;
60 //
61 // fields accumulated as we parse through documents
62 //
63 private String targetNamespace;
64 private QName serviceName;
65 private QName portName;
66 private String portAddress;
68 // true inside <wsdl:service>/<wsdl:part>/<wsa:EndpointReference>
69 private boolean inEpr;
70 // true inside <wsdl:service>/<wsdl:part>/<wsa:EndpointReference>/<wsa:Address>
71 private boolean inEprAddress;
73 /**
74 * Creates a {@link WSDLPatcher} for patching WSDL.
75 *
76 * @param portAddressResolver
77 * address of the endpoint is resolved using this docResolver.
78 * @param docResolver
79 * Consulted to get the import/include document locations.
80 * Must not be null.
81 */
82 public WSDLPatcher(@NotNull PortAddressResolver portAddressResolver,
83 @NotNull DocumentLocationResolver docResolver) {
84 this.portAddressResolver = portAddressResolver;
85 this.docResolver = docResolver;
86 }
88 @Override
89 protected void handleAttribute(int i) throws XMLStreamException {
90 QName name = in.getName();
91 String attLocalName = in.getAttributeLocalName(i);
93 if((name.equals(SCHEMA_INCLUDE_QNAME) && attLocalName.equals("schemaLocation"))
94 || (name.equals(SCHEMA_IMPORT_QNAME) && attLocalName.equals("schemaLocation"))
95 || (name.equals(SCHEMA_REDEFINE_QNAME) && attLocalName.equals("schemaLocation"))
96 || (name.equals(WSDLConstants.QNAME_IMPORT) && attLocalName.equals("location"))) {
97 // patch this attribute value.
99 String relPath = in.getAttributeValue(i);
100 String actualPath = getPatchedImportLocation(relPath);
101 if (actualPath == null) {
102 return; // skip this attribute to leave it up to "implicit reference".
103 }
105 logger.fine("Fixing the relative location:"+relPath
106 +" with absolute location:"+actualPath);
107 writeAttribute(i, actualPath);
108 return;
109 }
111 if (name.equals(WSDLConstants.NS_SOAP_BINDING_ADDRESS) ||
112 name.equals(WSDLConstants.NS_SOAP12_BINDING_ADDRESS)) {
114 if(attLocalName.equals("location")) {
115 portAddress = in.getAttributeValue(i);
116 String value = getAddressLocation();
117 if (value != null) {
118 logger.fine("Service:"+serviceName+ " port:"+portName
119 + " current address "+portAddress+" Patching it with "+value);
120 writeAttribute(i, value);
121 return;
122 }
123 }
124 }
126 super.handleAttribute(i);
127 }
129 /**
130 * Writes out an {@code i}-th attribute but with a different value.
131 * @param i attribute index
132 * @param value attribute value
133 * @throws XMLStreamException when an error encountered while writing attribute
134 */
135 private void writeAttribute(int i, String value) throws XMLStreamException {
136 String nsUri = in.getAttributeNamespace(i);
137 if(nsUri!=null)
138 out.writeAttribute( in.getAttributePrefix(i), nsUri, in.getAttributeLocalName(i), value );
139 else
140 out.writeAttribute( in.getAttributeLocalName(i), value );
141 }
143 @Override
144 protected void handleStartElement() throws XMLStreamException {
145 QName name = in.getName();
147 if (name.equals(WSDLConstants.QNAME_DEFINITIONS)) {
148 String value = in.getAttributeValue(null,"targetNamespace");
149 if (value != null) {
150 targetNamespace = value;
151 }
152 } else if (name.equals(WSDLConstants.QNAME_SERVICE)) {
153 String value = in.getAttributeValue(null,"name");
154 if (value != null) {
155 serviceName = new QName(targetNamespace, value);
156 }
157 } else if (name.equals(WSDLConstants.QNAME_PORT)) {
158 String value = in.getAttributeValue(null,"name");
159 if (value != null) {
160 portName = new QName(targetNamespace,value);
161 }
162 } else if (name.equals(W3CAddressingConstants.WSA_EPR_QNAME)
163 || name.equals(MemberSubmissionAddressingConstants.WSA_EPR_QNAME)) {
164 if (serviceName != null && portName != null) {
165 inEpr = true;
166 }
167 } else if (name.equals(W3CAddressingConstants.WSA_ADDRESS_QNAME)
168 || name.equals(MemberSubmissionAddressingConstants.WSA_ADDRESS_QNAME)) {
169 if (inEpr) {
170 inEprAddress = true;
171 }
172 }
173 super.handleStartElement();
174 }
176 @Override
177 protected void handleEndElement() throws XMLStreamException {
178 QName name = in.getName();
179 if (name.equals(WSDLConstants.QNAME_SERVICE)) {
180 serviceName = null;
181 } else if (name.equals(WSDLConstants.QNAME_PORT)) {
182 portName = null;
183 } else if (name.equals(W3CAddressingConstants.WSA_EPR_QNAME)
184 || name.equals(MemberSubmissionAddressingConstants.WSA_EPR_QNAME)) {
185 if (inEpr) {
186 inEpr = false;
187 }
188 } else if (name.equals(W3CAddressingConstants.WSA_ADDRESS_QNAME)
189 || name.equals(MemberSubmissionAddressingConstants.WSA_ADDRESS_QNAME)) {
190 if (inEprAddress) {
191 String value = getAddressLocation();
192 if (value != null) {
193 logger.fine("Fixing EPR Address for service:"+serviceName+ " port:"+portName
194 + " address with "+value);
195 out.writeCharacters(value);
196 }
197 inEprAddress = false;
198 }
199 }
200 super.handleEndElement();
201 }
203 @Override
204 protected void handleCharacters() throws XMLStreamException {
205 // handleCharacters() may be called multiple times.
206 if (inEprAddress) {
207 String value = getAddressLocation();
208 if (value != null) {
209 // will write the address with <wsa:Address> end element
210 return;
211 }
212 }
213 super.handleCharacters();
214 }
216 /**
217 * Returns the location to be placed into the generated document.
218 *
219 * @param relPath relative URI to be resolved
220 * @return
221 * null to leave it to the "implicit reference".
222 */
223 private @Nullable String getPatchedImportLocation(String relPath) {
224 return docResolver.getLocationFor(null, relPath);
225 }
227 /**
228 * For the given service, port names it matches the correct endpoint and
229 * reutrns its endpoint address
230 *
231 * @return returns the resolved endpoint address
232 */
233 private String getAddressLocation() {
234 return (portAddressResolver == null || portName == null)
235 ? null : portAddressResolver.getAddressFor(serviceName, portName.getLocalPart(), portAddress);
236 }
237 }