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.protocol.soap;
27
28import com.sun.xml.internal.ws.api.SOAPVersion;
29import static com.sun.xml.internal.ws.api.SOAPVersion.SOAP_11;
30import static com.sun.xml.internal.ws.api.SOAPVersion.SOAP_12;
31import com.sun.xml.internal.ws.api.WSBinding;
32import com.sun.xml.internal.ws.api.message.Header;
33import com.sun.xml.internal.ws.api.message.Message;
34import com.sun.xml.internal.ws.api.message.MessageHeaders;
35import com.sun.xml.internal.ws.api.pipe.Tube;
36import com.sun.xml.internal.ws.api.pipe.TubeCloner;
37import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterTubeImpl;
38import com.sun.xml.internal.ws.binding.SOAPBindingImpl;
39import com.sun.xml.internal.ws.message.DOMHeader;
40import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
41import org.w3c.dom.Element;
42
43import javax.xml.namespace.QName;
44import javax.xml.soap.SOAPElement;
45import javax.xml.soap.SOAPException;
46import javax.xml.soap.SOAPFault;
47import javax.xml.ws.WebServiceException;
48import javax.xml.ws.soap.SOAPBinding;
49import javax.xml.ws.soap.SOAPFaultException;
50import java.util.Set;
51import java.util.logging.Logger;
52
53/**
54 * @author Rama Pulavarthi
55 */
56
57abstract class MUTube extends AbstractFilterTubeImpl {
58
59    private static final String MU_FAULT_DETAIL_LOCALPART = "NotUnderstood";
60    private final static QName MU_HEADER_DETAIL = new QName(SOAPVersion.SOAP_12.nsUri, MU_FAULT_DETAIL_LOCALPART);
61    //TODO: change
62    protected static final Logger logger = Logger.getLogger(
63            com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".soap.decoder");
64    private final static String MUST_UNDERSTAND_FAULT_MESSAGE_STRING =
65            "One or more mandatory SOAP header blocks not understood";
66
67    protected final SOAPVersion soapVersion;
68    protected SOAPBindingImpl binding;
69
70    protected MUTube(WSBinding binding, Tube next) {
71        super(next);
72        // MUPipe should n't be used for bindings other than SOAP.
73        if (!(binding instanceof SOAPBinding)) {
74            throw new WebServiceException(
75                    "MUPipe should n't be used for bindings other than SOAP.");
76        }
77        this.binding = (SOAPBindingImpl) binding;
78        this.soapVersion = binding.getSOAPVersion();
79    }
80
81    protected MUTube(MUTube that, TubeCloner cloner) {
82        super(that, cloner);
83        binding = that.binding;
84        soapVersion = that.soapVersion;
85    }
86
87    /**
88     * @param headers HeaderList that needs MU processing
89     * @param roles        Roles configured on the Binding. Required Roles supposed to be assumbed a by a
90     *                     SOAP Binding implementation are added.
91     * @param handlerKnownHeaders Set of headers that the handlerchain associated with the binding understands
92     * @return returns the headers that have mustUnderstand attribute and are not understood
93     *         by the binding.
94     */
95    public final Set<QName> getMisUnderstoodHeaders(MessageHeaders headers, Set<String> roles,
96                                                    Set<QName> handlerKnownHeaders) {
97        return headers.getNotUnderstoodHeaders(roles, handlerKnownHeaders, binding);
98
99    }
100
101    /**
102     * @param notUnderstoodHeaders
103     * @return SOAPfaultException with SOAPFault representing the MustUnderstand SOAP Fault.
104     *         notUnderstoodHeaders are added in the fault detail.
105     */
106    final SOAPFaultException createMUSOAPFaultException(Set<QName> notUnderstoodHeaders) {
107        try {
108            SOAPFault fault = soapVersion.getSOAPFactory().createFault(
109                MUST_UNDERSTAND_FAULT_MESSAGE_STRING,
110                soapVersion.faultCodeMustUnderstand);
111            fault.setFaultString("MustUnderstand headers:" +
112                notUnderstoodHeaders + " are not understood");
113            return new SOAPFaultException(fault);
114        } catch (SOAPException e) {
115            throw new WebServiceException(e);
116        }
117    }
118
119    /**
120     * This should be used only in ServerMUPipe
121     *
122     * @param notUnderstoodHeaders
123     * @return Message representing a SOAPFault
124     *         In SOAP 1.1, notUnderstoodHeaders are added in the fault Detail
125     *         in SOAP 1.2, notUnderstoodHeaders are added as the SOAP Headers
126     */
127
128    final Message createMUSOAPFaultMessage(Set<QName> notUnderstoodHeaders) {
129        try {
130            String faultString = MUST_UNDERSTAND_FAULT_MESSAGE_STRING;
131            if (soapVersion == SOAP_11) {
132                faultString = "MustUnderstand headers:" + notUnderstoodHeaders + " are not understood";
133            }
134            Message  muFaultMessage = SOAPFaultBuilder.createSOAPFaultMessage(
135                    soapVersion,faultString,soapVersion.faultCodeMustUnderstand);
136
137            if (soapVersion == SOAP_12) {
138                addHeader(muFaultMessage, notUnderstoodHeaders);
139            }
140            return muFaultMessage;
141        } catch (SOAPException e) {
142            throw new WebServiceException(e);
143        }
144    }
145
146    private static void addHeader(Message m, Set<QName> notUnderstoodHeaders) throws SOAPException {
147        for (QName qname : notUnderstoodHeaders) {
148            SOAPElement soapEl = SOAP_12.getSOAPFactory().createElement(MU_HEADER_DETAIL);
149            soapEl.addNamespaceDeclaration("abc", qname.getNamespaceURI());
150            soapEl.setAttribute("qname", "abc:" + qname.getLocalPart());
151            Header header = new DOMHeader<Element>(soapEl);
152            m.getHeaders().add(header);
153        }
154    }
155}
156