1/*
2 * Copyright (c) 1997, 2013, 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.addressing.model.InvalidAddressingHeaderException;
29import com.sun.xml.internal.ws.addressing.model.MissingAddressingHeaderException;
30import com.sun.xml.internal.ws.api.SOAPVersion;
31import com.sun.xml.internal.ws.api.WSBinding;
32import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
33import com.sun.xml.internal.ws.api.message.AddressingUtils;
34import com.sun.xml.internal.ws.api.message.Packet;
35import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
36import com.sun.xml.internal.ws.api.model.wsdl.WSDLFault;
37import com.sun.xml.internal.ws.api.model.wsdl.WSDLOperation;
38import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
39import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
40import com.sun.xml.internal.ws.api.model.SEIModel;
41import com.sun.xml.internal.ws.api.model.JavaMethod;
42import com.sun.xml.internal.ws.api.model.WSDLOperationMapping;
43import com.sun.xml.internal.ws.model.JavaMethodImpl;
44import com.sun.xml.internal.ws.model.CheckedExceptionImpl;
45import com.sun.istack.internal.Nullable;
46import org.w3c.dom.Element;
47
48import javax.xml.namespace.QName;
49import javax.xml.soap.Detail;
50import javax.xml.soap.SOAPConstants;
51import javax.xml.soap.SOAPException;
52import javax.xml.soap.SOAPFactory;
53import javax.xml.soap.SOAPFault;
54import javax.xml.soap.SOAPMessage;
55import javax.xml.ws.WebServiceException;
56
57/**
58 * @author Rama Pulavarthi
59 * @author Arun Gupta
60 */
61public abstract class WsaTubeHelper {
62
63    public WsaTubeHelper(WSBinding binding, SEIModel seiModel, WSDLPort wsdlPort) {
64        this.binding = binding;
65        this.wsdlPort = wsdlPort;
66        this.seiModel = seiModel;
67        this.soapVer = binding.getSOAPVersion();
68        this.addVer = binding.getAddressingVersion();
69
70    }
71
72    public String getFaultAction(Packet requestPacket, Packet responsePacket) {
73        String action = null;
74        if(seiModel != null) {
75            action = getFaultActionFromSEIModel(requestPacket,responsePacket);
76        }
77        if (action != null) {
78            return action;
79        } else {
80            action = addVer.getDefaultFaultAction();
81        }
82        if (wsdlPort != null) {
83            WSDLOperationMapping wsdlOp = requestPacket.getWSDLOperationMapping();
84            if (wsdlOp != null) {
85                WSDLBoundOperation wbo = wsdlOp.getWSDLBoundOperation();
86                return getFaultAction(wbo, responsePacket);
87            }
88        }
89        return action;
90    }
91
92    String getFaultActionFromSEIModel(Packet requestPacket, Packet responsePacket) {
93        String action = null;
94        if (seiModel == null || wsdlPort == null) {
95            return action;
96        }
97
98        try {
99            SOAPMessage sm = responsePacket.getMessage().copy().readAsSOAPMessage();
100            if (sm == null) {
101                return action;
102            }
103
104            if (sm.getSOAPBody() == null) {
105                return action;
106            }
107
108            if (sm.getSOAPBody().getFault() == null) {
109                return action;
110            }
111
112            Detail detail = sm.getSOAPBody().getFault().getDetail();
113            if (detail == null) {
114                return action;
115            }
116
117            String ns = detail.getFirstChild().getNamespaceURI();
118            String name = detail.getFirstChild().getLocalName();
119
120            WSDLOperationMapping wsdlOp = requestPacket.getWSDLOperationMapping();
121            JavaMethodImpl jm = (wsdlOp != null) ? (JavaMethodImpl)wsdlOp.getJavaMethod() : null;
122            if (jm != null) {
123              for (CheckedExceptionImpl ce : jm.getCheckedExceptions()) {
124                  if (ce.getDetailType().tagName.getLocalPart().equals(name) &&
125                          ce.getDetailType().tagName.getNamespaceURI().equals(ns)) {
126                      return ce.getFaultAction();
127                  }
128              }
129            }
130            return action;
131        } catch (SOAPException e) {
132            throw new WebServiceException(e);
133        }
134    }
135
136    String getFaultAction(@Nullable WSDLBoundOperation wbo, Packet responsePacket) {
137        String action = AddressingUtils.getAction(responsePacket.getMessage().getHeaders(), addVer, soapVer);
138        if (action != null) {
139            return action;
140        }
141
142        action = addVer.getDefaultFaultAction();
143        if (wbo == null) {
144            return action;
145        }
146
147        try {
148            SOAPMessage sm = responsePacket.getMessage().copy().readAsSOAPMessage();
149            if (sm == null) {
150                return action;
151            }
152
153            if (sm.getSOAPBody() == null) {
154                return action;
155            }
156
157            if (sm.getSOAPBody().getFault() == null) {
158                return action;
159            }
160
161            Detail detail = sm.getSOAPBody().getFault().getDetail();
162            if (detail == null) {
163                return action;
164            }
165
166            String ns = detail.getFirstChild().getNamespaceURI();
167            String name = detail.getFirstChild().getLocalName();
168
169            WSDLOperation o = wbo.getOperation();
170
171            WSDLFault fault = o.getFault(new QName(ns, name));
172            if (fault == null) {
173                return action;
174            }
175
176            action = fault.getAction();
177
178            return action;
179        } catch (SOAPException e) {
180            throw new WebServiceException(e);
181        }
182    }
183
184    public String getInputAction(Packet packet) {
185        String action = null;
186
187        if (wsdlPort != null) {
188            WSDLOperationMapping wsdlOp = packet.getWSDLOperationMapping();
189            if (wsdlOp != null) {
190                WSDLBoundOperation wbo = wsdlOp.getWSDLBoundOperation();
191                WSDLOperation op = wbo.getOperation();
192                action = op.getInput().getAction();
193            }
194        }
195
196        return action;
197    }
198
199    /**
200     * This method gives the Input addressing Action for a message.
201     * It gives the Action set in the wsdl operation for the corresponding payload.
202     * If it is not explicitly set, it gives the soapAction
203     * @param packet
204     * @return input Action
205     */
206    public String getEffectiveInputAction(Packet packet) {
207        //non-default SOAPAction beomes wsa:action
208        if(packet.soapAction != null && !packet.soapAction.equals("")) {
209            return packet.soapAction;
210        }
211        String action;
212
213        if (wsdlPort != null) {
214            WSDLOperationMapping wsdlOp = packet.getWSDLOperationMapping();
215            if (wsdlOp != null) {
216                WSDLBoundOperation wbo = wsdlOp.getWSDLBoundOperation();
217                WSDLOperation op = wbo.getOperation();
218                action = op.getInput().getAction();
219            } else {
220                action = packet.soapAction;
221            }
222        } else {
223            action = packet.soapAction;
224        }
225        return action;
226    }
227
228    public boolean isInputActionDefault(Packet packet) {
229        if (wsdlPort == null) {
230            return false;
231        }
232        WSDLOperationMapping wsdlOp = packet.getWSDLOperationMapping();
233        if(wsdlOp == null) {
234            return false;
235        }
236        WSDLBoundOperation wbo = wsdlOp.getWSDLBoundOperation();
237        WSDLOperation op = wbo.getOperation();
238        return op.getInput().isDefaultAction();
239
240    }
241
242    public String getSOAPAction(Packet packet) {
243        String action = "";
244
245        if (packet == null || packet.getMessage() == null) {
246            return action;
247        }
248
249        if (wsdlPort == null) {
250            return action;
251        }
252
253        WSDLOperationMapping wsdlOp = packet.getWSDLOperationMapping();
254        if (wsdlOp == null) {
255            return action;
256        }
257
258        WSDLBoundOperation op = wsdlOp.getWSDLBoundOperation();
259        action = op.getSOAPAction();
260        return action;
261    }
262
263    public String getOutputAction(Packet packet) {
264        //String action = AddressingVersion.UNSET_OUTPUT_ACTION;
265        String action = null;
266        WSDLOperationMapping wsdlOp = packet.getWSDLOperationMapping();
267        if (wsdlOp != null) {
268            JavaMethod javaMethod = wsdlOp.getJavaMethod();
269            if (javaMethod != null) {
270                JavaMethodImpl jm = (JavaMethodImpl) javaMethod;
271                if (jm != null && jm.getOutputAction() != null && !jm.getOutputAction().equals("")) {
272                    return jm.getOutputAction();
273                }
274            }
275            WSDLBoundOperation wbo = wsdlOp.getWSDLBoundOperation();
276            if (wbo != null) return getOutputAction(wbo);
277        }
278        return action;
279    }
280
281    String getOutputAction(@Nullable WSDLBoundOperation wbo) {
282        String action = AddressingVersion.UNSET_OUTPUT_ACTION;
283        if (wbo != null) {
284            WSDLOutput op = wbo.getOperation().getOutput();
285            if (op != null) {
286                action = op.getAction();
287            }
288        }
289        return action;
290    }
291
292    public SOAPFault createInvalidAddressingHeaderFault(InvalidAddressingHeaderException e, AddressingVersion av) {
293        QName name = e.getProblemHeader();
294        QName subsubcode = e.getSubsubcode();
295        QName subcode = av.invalidMapTag;
296        String faultstring = String.format(av.getInvalidMapText(), name, subsubcode);
297
298        try {
299            SOAPFactory factory;
300            SOAPFault fault;
301            if (soapVer == SOAPVersion.SOAP_12) {
302                factory = SOAPVersion.SOAP_12.getSOAPFactory();
303                fault = factory.createFault();
304                fault.setFaultCode(SOAPConstants.SOAP_SENDER_FAULT);
305                fault.appendFaultSubcode(subcode);
306                fault.appendFaultSubcode(subsubcode);
307                getInvalidMapDetail(name, fault.addDetail());
308            } else {
309                factory = SOAPVersion.SOAP_11.getSOAPFactory();
310                fault = factory.createFault();
311                fault.setFaultCode(subsubcode);
312            }
313
314            fault.setFaultString(faultstring);
315
316            return fault;
317        } catch (SOAPException se) {
318            throw new WebServiceException(se);
319        }
320    }
321
322    public SOAPFault newMapRequiredFault(MissingAddressingHeaderException e) {
323        QName subcode = addVer.mapRequiredTag;
324        QName subsubcode = addVer.mapRequiredTag;
325        String faultstring = addVer.getMapRequiredText();
326
327        try {
328            SOAPFactory factory;
329            SOAPFault fault;
330            if (soapVer == SOAPVersion.SOAP_12) {
331                factory = SOAPVersion.SOAP_12.getSOAPFactory();
332                fault = factory.createFault();
333                fault.setFaultCode(SOAPConstants.SOAP_SENDER_FAULT);
334                fault.appendFaultSubcode(subcode);
335                fault.appendFaultSubcode(subsubcode);
336                getMapRequiredDetail(e.getMissingHeaderQName(), fault.addDetail());
337            } else {
338                factory = SOAPVersion.SOAP_11.getSOAPFactory();
339                fault = factory.createFault();
340                fault.setFaultCode(subsubcode);
341            }
342
343            fault.setFaultString(faultstring);
344
345            return fault;
346        } catch (SOAPException se) {
347            throw new WebServiceException(se);
348        }
349    }
350
351    public abstract void getProblemActionDetail(String action, Element element);
352    public abstract void getInvalidMapDetail(QName name, Element element);
353    public abstract void getMapRequiredDetail(QName name, Element element);
354
355    protected SEIModel seiModel;
356    protected WSDLPort wsdlPort;
357    protected WSBinding binding;
358    protected final SOAPVersion soapVer;
359    protected final AddressingVersion addVer;
360}
361