1/*
2 * Copyright (c) 1997, 2014, 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 */
25
26package com.sun.xml.internal.ws.addressing;
27
28import com.sun.xml.internal.ws.api.server.*;
29import com.sun.xml.internal.ws.api.server.Module;
30import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
31import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
32import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
33import com.sun.xml.internal.ws.util.xml.XMLStreamWriterFilter;
34import com.sun.xml.internal.org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter;
35import com.sun.xml.internal.ws.server.WSEndpointImpl;
36import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants;
37import com.sun.istack.internal.Nullable;
38import com.sun.istack.internal.NotNull;
39
40import javax.xml.stream.XMLStreamWriter;
41import javax.xml.stream.XMLStreamException;
42import javax.xml.stream.XMLStreamReader;
43import javax.xml.namespace.NamespaceContext;
44import java.io.IOException;
45import java.util.List;
46import java.util.Collection;
47import java.util.Collections;
48
49/**
50 * This class acts as a filter for the Extension elements in the wsa:EndpointReference in the wsdl.
51 * In addition to filtering the EPR extensions from WSDL, it adds the extensions configured by the JAX-WS runtime
52 * specifc to an endpoint.
53 *
54 * @author Rama Pulavarthi
55 */
56public class EPRSDDocumentFilter implements SDDocumentFilter {
57    private final WSEndpointImpl<?> endpoint;
58    //initialize lazily
59    List<BoundEndpoint> beList;
60    public EPRSDDocumentFilter(@NotNull WSEndpointImpl<?> endpoint) {
61        this.endpoint = endpoint;
62    }
63
64    private @Nullable WSEndpointImpl<?> getEndpoint(String serviceName, String portName) {
65        if (serviceName == null || portName == null)
66            return null;
67        if (endpoint.getServiceName().getLocalPart().equals(serviceName) && endpoint.getPortName().getLocalPart().equals(portName))
68            return endpoint;
69
70        if(beList == null) {
71            //check if it is run in a Java EE Container and get hold of other endpoints in the application
72            Module module = endpoint.getContainer().getSPI(Module.class);
73            if (module != null) {
74                beList = module.getBoundEndpoints();
75            } else {
76                beList = Collections.<BoundEndpoint>emptyList();
77            }
78        }
79
80        for (BoundEndpoint be : beList) {
81            WSEndpoint wse = be.getEndpoint();
82            if (wse.getServiceName().getLocalPart().equals(serviceName) && wse.getPortName().getLocalPart().equals(portName)) {
83                return (WSEndpointImpl) wse;
84            }
85        }
86
87        return null;
88
89    }
90
91    public XMLStreamWriter filter(SDDocument doc, XMLStreamWriter w) throws XMLStreamException, IOException {
92        if (!doc.isWSDL()) {
93            return w;
94        }
95
96        return new XMLStreamWriterFilter(w) {
97            private boolean eprExtnFilterON = false; //when true, all writer events are filtered out
98
99            private boolean portHasEPR = false;
100            private int eprDepth = -1; // -1 -> outside wsa:epr, 0 -> on wsa:epr start/end , > 0 inside wsa:epr
101
102            private String serviceName = null; //non null when inside wsdl:service scope
103            private boolean onService = false; //flag to get service name when on wsdl:service element start
104            private int serviceDepth = -1;  // -1 -> outside wsdl:service, 0 -> on wsdl:service start/end , > 0 inside wsdl:service
105
106            private String portName = null; //non null when inside wsdl:port scope
107            private boolean onPort = false; //flag to get port name when on wsdl:port element start
108            private int portDepth = -1; // -1 -> outside wsdl:port, 0 -> on wsdl:port start/end , > 0 inside wsdl:port
109
110            private String portAddress; // when a complete epr is written, endpoint address is used as epr address
111            private boolean onPortAddress = false; //flag to get endpoint address when on soap:address element start
112
113            private void handleStartElement(String localName, String namespaceURI) throws XMLStreamException {
114                resetOnElementFlags();
115                if (serviceDepth >= 0) {
116                    serviceDepth++;
117                }
118                if (portDepth >= 0) {
119                    portDepth++;
120                }
121                if (eprDepth >= 0) {
122                    eprDepth++;
123                }
124
125                if (namespaceURI.equals(WSDLConstants.QNAME_SERVICE.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_SERVICE.getLocalPart())) {
126                    onService = true;
127                    serviceDepth = 0;
128                } else if (namespaceURI.equals(WSDLConstants.QNAME_PORT.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_PORT.getLocalPart())) {
129                    if (serviceDepth >= 1) {
130                        onPort = true;
131                        portDepth = 0;
132                    }
133                } else if (namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME) && localName.equals("EndpointReference")) {
134                    if (serviceDepth >= 1 && portDepth >= 1) {
135                        portHasEPR = true;
136                        eprDepth = 0;
137                    }
138                } else if ((namespaceURI.equals(WSDLConstants.NS_SOAP_BINDING_ADDRESS.getNamespaceURI()) || namespaceURI.equals(WSDLConstants.NS_SOAP12_BINDING_ADDRESS.getNamespaceURI()))
139                        &&  localName.equals("address") && portDepth ==1) {
140                    onPortAddress = true;
141                }
142                WSEndpoint endpoint = getEndpoint(serviceName,portName);
143                //filter epr for only for the port corresponding to this endpoint
144                //if (service.getLocalPart().equals(serviceName) && port.getLocalPart().equals(portName)) {
145                if ( endpoint != null) {
146                    if ((eprDepth == 1) && !namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME)) {
147                        //epr extension element
148                        eprExtnFilterON = true;
149
150                    }
151
152                    /*
153                    if (eprExtnFilterON) {
154                        writeEPRExtensions();
155                    }
156                    */
157                }
158            }
159
160            private void resetOnElementFlags() {
161                if (onService) {
162                    onService = false;
163                }
164                if (onPort) {
165                    onPort = false;
166                }
167                if (onPortAddress) {
168                    onPortAddress = false;
169                }
170
171            }
172
173
174            private void writeEPRExtensions(Collection<WSEndpointReference.EPRExtension> eprExtns) throws XMLStreamException {
175               if (eprExtns != null) {
176                        for (WSEndpointReference.EPRExtension e : eprExtns) {
177                            XMLStreamReaderToXMLStreamWriter c = new XMLStreamReaderToXMLStreamWriter();
178                            XMLStreamReader r = e.readAsXMLStreamReader();
179                            c.bridge(r, writer);
180                            XMLStreamReaderFactory.recycle(r);
181                        }
182                    }
183            }
184
185            @Override
186            public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
187                handleStartElement(localName, namespaceURI);
188                if (!eprExtnFilterON) {
189                    super.writeStartElement(prefix, localName, namespaceURI);
190                }
191            }
192
193            @Override
194            public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
195                handleStartElement(localName, namespaceURI);
196                if (!eprExtnFilterON) {
197                    super.writeStartElement(namespaceURI, localName);
198                }
199            }
200
201            @Override
202            public void writeStartElement(String localName) throws XMLStreamException {
203                if (!eprExtnFilterON) {
204                    super.writeStartElement(localName);
205                }
206            }
207
208            private void handleEndElement() throws XMLStreamException {
209                resetOnElementFlags();
210                //End of wsdl:port, write complete EPR if not present.
211                if (portDepth == 0) {
212
213                    if (!portHasEPR && getEndpoint(serviceName,portName) != null) {
214
215                        //write the complete EPR with address.
216                        writer.writeStartElement(AddressingVersion.W3C.getPrefix(),"EndpointReference", AddressingVersion.W3C.nsUri );
217                        writer.writeNamespace(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.nsUri);
218                        writer.writeStartElement(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.eprType.address, AddressingVersion.W3C.nsUri);
219                        writer.writeCharacters(portAddress);
220                        writer.writeEndElement();
221                        writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions());
222                        writer.writeEndElement();
223
224                    }
225                }
226                //End of wsa:EndpointReference, write EPR extension elements
227                if (eprDepth == 0) {
228                    if (portHasEPR && getEndpoint(serviceName,portName) != null) {
229                        writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions());
230                    }
231                    eprExtnFilterON = false;
232                }
233
234                if(serviceDepth >= 0 )  {
235                    serviceDepth--;
236                }
237                if(portDepth >= 0) {
238                    portDepth--;
239                }
240                if(eprDepth >=0) {
241                    eprDepth--;
242                }
243
244                if (serviceDepth == -1) {
245                    serviceName = null;
246                }
247                if (portDepth == -1) {
248                    portHasEPR = false;
249                    portAddress = null;
250                    portName = null;
251                }
252            }
253
254            @Override
255            public void writeEndElement() throws XMLStreamException {
256                handleEndElement();
257                if (!eprExtnFilterON) {
258                    super.writeEndElement();
259                }
260            }
261
262            private void handleAttribute(String localName, String value) {
263                if (localName.equals("name")) {
264                    if (onService) {
265                        serviceName = value;
266                        onService = false;
267                    } else if (onPort) {
268                        portName = value;
269                        onPort = false;
270                    }
271                }
272                if (localName.equals("location") && onPortAddress) {
273                    portAddress = value;
274                }
275
276
277            }
278
279            @Override
280            public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
281                handleAttribute(localName, value);
282                if (!eprExtnFilterON) {
283                    super.writeAttribute(prefix, namespaceURI, localName, value);
284                }
285            }
286
287            @Override
288            public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
289                handleAttribute(localName, value);
290                if (!eprExtnFilterON) {
291                    super.writeAttribute(namespaceURI, localName, value);
292                }
293            }
294
295            @Override
296            public void writeAttribute(String localName, String value) throws XMLStreamException {
297                handleAttribute(localName, value);
298                if (!eprExtnFilterON) {
299                    super.writeAttribute(localName, value);
300                }
301            }
302
303
304            @Override
305            public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
306                if (!eprExtnFilterON) {
307                    super.writeEmptyElement(namespaceURI, localName);
308                }
309            }
310
311            @Override
312            public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
313                if (!eprExtnFilterON) {
314                    super.writeNamespace(prefix, namespaceURI);
315                }
316            }
317
318            @Override
319            public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
320                if (!eprExtnFilterON) {
321                    super.setNamespaceContext(context);
322                }
323            }
324
325            @Override
326            public void setDefaultNamespace(String uri) throws XMLStreamException {
327                if (!eprExtnFilterON) {
328                    super.setDefaultNamespace(uri);
329                }
330            }
331
332            @Override
333            public void setPrefix(String prefix, String uri) throws XMLStreamException {
334                if (!eprExtnFilterON) {
335                    super.setPrefix(prefix, uri);
336                }
337            }
338
339            @Override
340            public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
341                if (!eprExtnFilterON) {
342                    super.writeProcessingInstruction(target, data);
343                }
344            }
345
346            @Override
347            public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
348                if (!eprExtnFilterON) {
349                    super.writeEmptyElement(prefix, localName, namespaceURI);
350                }
351            }
352
353            @Override
354            public void writeCData(String data) throws XMLStreamException {
355                if (!eprExtnFilterON) {
356                    super.writeCData(data);
357                }
358            }
359
360            @Override
361            public void writeCharacters(String text) throws XMLStreamException {
362                if (!eprExtnFilterON) {
363                    super.writeCharacters(text);
364                }
365            }
366
367            @Override
368            public void writeComment(String data) throws XMLStreamException {
369                if (!eprExtnFilterON) {
370                    super.writeComment(data);
371                }
372            }
373
374            @Override
375            public void writeDTD(String dtd) throws XMLStreamException {
376                if (!eprExtnFilterON) {
377                    super.writeDTD(dtd);
378                }
379            }
380
381            @Override
382            public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
383                if (!eprExtnFilterON) {
384                    super.writeDefaultNamespace(namespaceURI);
385                }
386            }
387
388            @Override
389            public void writeEmptyElement(String localName) throws XMLStreamException {
390                if (!eprExtnFilterON) {
391                    super.writeEmptyElement(localName);
392                }
393            }
394
395            @Override
396            public void writeEntityRef(String name) throws XMLStreamException {
397                if (!eprExtnFilterON) {
398                    super.writeEntityRef(name);
399                }
400            }
401
402            @Override
403            public void writeProcessingInstruction(String target) throws XMLStreamException {
404                if (!eprExtnFilterON) {
405                    super.writeProcessingInstruction(target);
406                }
407            }
408
409
410            @Override
411            public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
412                if (!eprExtnFilterON) {
413                    super.writeCharacters(text, start, len);
414                }
415            }
416
417        };
418
419    }
420
421}
422