View Javadoc
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  
26  package com.sun.xml.internal.ws.binding;
27  
28  import com.oracle.webservices.internal.api.message.MessageContextFactory;
29  import com.sun.istack.internal.NotNull;
30  import com.sun.istack.internal.Nullable;
31  import com.sun.xml.internal.ws.api.BindingID;
32  import com.sun.xml.internal.ws.api.SOAPVersion;
33  import com.sun.xml.internal.ws.api.WSBinding;
34  import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
35  import com.sun.xml.internal.ws.api.pipe.Codec;
36  import com.sun.xml.internal.ws.client.HandlerConfiguration;
37  import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature;
38  import com.sun.xml.internal.ws.developer.BindingTypeFeature;
39  
40  import javax.xml.namespace.QName;
41  import javax.xml.ws.Service;
42  import javax.xml.ws.WebServiceFeature;
43  import javax.xml.ws.soap.AddressingFeature;
44  import javax.xml.ws.handler.Handler;
45  import java.util.Collections;
46  import java.util.HashMap;
47  import java.util.HashSet;
48  import java.util.List;
49  import java.util.Set;
50  import java.util.Map;
51  
52  
53  /**
54   * Instances are created by the service, which then
55   * sets the handler chain on the binding impl.
56   *
57   * <p>
58   * This class is made abstract as we don't see a situation when
59   * a BindingImpl has much meaning without binding id.
60   * IOW, for a specific binding there will be a class
61   * extending BindingImpl, for example SOAPBindingImpl.
62   *
63   * <p>
64   * The spi Binding interface extends Binding.
65   *
66   * @author WS Development Team
67   */
68  public abstract class BindingImpl implements WSBinding {
69  
70      protected static final WebServiceFeature[] EMPTY_FEATURES = new WebServiceFeature[0];
71  
72      //This is reset when ever Binding.setHandlerChain() or SOAPBinding.setRoles() is called.
73      private HandlerConfiguration handlerConfig;
74      private final Set<QName> addedHeaders = new HashSet<QName>();
75      private final Set<QName> knownHeaders = new HashSet<QName>();
76      private final Set<QName> unmodKnownHeaders = Collections.unmodifiableSet(knownHeaders);
77      private final BindingID bindingId;
78      // Features that are set(enabled/disabled) on the binding
79      protected final WebServiceFeatureList features;
80      // Features that are set(enabled/disabled) on the binding or an operation
81      protected final Map<QName, WebServiceFeatureList> operationFeatures = new HashMap<QName, WebServiceFeatureList>();
82      // Features that are set(enabled/disabled) on the binding, an operation or an input message
83      protected final Map<QName, WebServiceFeatureList> inputMessageFeatures = new HashMap<QName, WebServiceFeatureList>();
84      // Features that are set(enabled/disabled) on the binding, an operation or an output message
85      protected final Map<QName, WebServiceFeatureList> outputMessageFeatures = new HashMap<QName, WebServiceFeatureList>();
86      // Features that are set(enabled/disabled) on the binding, an operation or a fault message
87      protected final Map<MessageKey, WebServiceFeatureList> faultMessageFeatures = new HashMap<MessageKey, WebServiceFeatureList>();
88  
89      protected javax.xml.ws.Service.Mode serviceMode = javax.xml.ws.Service.Mode.PAYLOAD;
90  
91      protected MessageContextFactory messageContextFactory;
92  
93      protected BindingImpl(BindingID bindingId, WebServiceFeature ... features) {
94          this.bindingId = bindingId;
95          handlerConfig = new HandlerConfiguration(Collections.<String>emptySet(), Collections.<Handler>emptyList());
96          if (handlerConfig.getHandlerKnownHeaders() != null)
97              knownHeaders.addAll(handlerConfig.getHandlerKnownHeaders());
98          this.features = new WebServiceFeatureList(features);
99          this.features.validate();
100     }
101 
102     public
103     @NotNull
104     List<Handler> getHandlerChain() {
105         return handlerConfig.getHandlerChain();
106     }
107 
108     public HandlerConfiguration getHandlerConfig() {
109         return handlerConfig;
110     }
111 
112     protected void setHandlerConfig(HandlerConfiguration handlerConfig) {
113         this.handlerConfig = handlerConfig;
114         knownHeaders.clear();
115         knownHeaders.addAll(addedHeaders);
116         if (handlerConfig != null && handlerConfig.getHandlerKnownHeaders() != null)
117             knownHeaders.addAll(handlerConfig.getHandlerKnownHeaders());
118     }
119 
120     public void setMode(@NotNull Service.Mode mode) {
121         this.serviceMode = mode;
122     }
123 
124     public Set<QName> getKnownHeaders() {
125         return unmodKnownHeaders;
126     }
127 
128     public boolean addKnownHeader(QName headerQName) {
129         addedHeaders.add(headerQName);
130         return knownHeaders.add(headerQName);
131     }
132 
133     public
134     @NotNull
135     BindingID getBindingId() {
136         return bindingId;
137     }
138 
139     public final SOAPVersion getSOAPVersion() {
140         return bindingId.getSOAPVersion();
141     }
142 
143     public AddressingVersion getAddressingVersion() {
144         AddressingVersion addressingVersion;
145         if (features.isEnabled(AddressingFeature.class))
146             addressingVersion = AddressingVersion.W3C;
147         else if (features.isEnabled(MemberSubmissionAddressingFeature.class))
148             addressingVersion = AddressingVersion.MEMBER;
149         else
150             addressingVersion = null;
151         return addressingVersion;
152     }
153 
154     public final
155     @NotNull
156     Codec createCodec() {
157         return bindingId.createEncoder(this);
158     }
159 
160     public static BindingImpl create(@NotNull BindingID bindingId) {
161         if (bindingId.equals(BindingID.XML_HTTP))
162             return new HTTPBindingImpl();
163         else
164             return new SOAPBindingImpl(bindingId);
165     }
166 
167     public static BindingImpl create(@NotNull BindingID bindingId, WebServiceFeature[] features) {
168         // Override the BindingID from the features
169         for(WebServiceFeature feature : features) {
170             if (feature instanceof BindingTypeFeature) {
171                 BindingTypeFeature f = (BindingTypeFeature)feature;
172                 bindingId = BindingID.parse(f.getBindingId());
173             }
174         }
175         if (bindingId.equals(BindingID.XML_HTTP))
176             return new HTTPBindingImpl(features);
177         else
178             return new SOAPBindingImpl(bindingId, features);
179     }
180 
181     public static WSBinding getDefaultBinding() {
182         return new SOAPBindingImpl(BindingID.SOAP11_HTTP);
183     }
184 
185     public String getBindingID() {
186         return bindingId.toString();
187     }
188 
189     public @Nullable <F extends WebServiceFeature> F getFeature(@NotNull Class<F> featureType){
190         return features.get(featureType);
191     }
192 
193     public @Nullable <F extends WebServiceFeature> F getOperationFeature(@NotNull Class<F> featureType,
194             @NotNull final QName operationName) {
195         final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName);
196         return FeatureListUtil.mergeFeature(featureType, operationFeatureList, features);
197     }
198 
199     public boolean isFeatureEnabled(@NotNull Class<? extends WebServiceFeature> feature){
200         return features.isEnabled(feature);
201     }
202 
203     public boolean isOperationFeatureEnabled(@NotNull Class<? extends WebServiceFeature> featureType,
204             @NotNull final QName operationName) {
205         final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName);
206         return FeatureListUtil.isFeatureEnabled(featureType, operationFeatureList, features);
207     }
208 
209     @NotNull
210     public WebServiceFeatureList getFeatures() {
211         //TODO scchen convert BindingID  to WebServiceFeature[]
212         if(!isFeatureEnabled(com.oracle.webservices.internal.api.EnvelopeStyleFeature.class)) {
213             WebServiceFeature[] f = { getSOAPVersion().toFeature() };
214             features.mergeFeatures(f, false);
215         }
216         return features;
217     }
218 
219     public @NotNull WebServiceFeatureList getOperationFeatures(@NotNull final QName operationName) {
220         final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName);
221         return FeatureListUtil.mergeList(operationFeatureList, features);
222     }
223 
224     public @NotNull WebServiceFeatureList getInputMessageFeatures(@NotNull final QName operationName) {
225         final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName);
226         final WebServiceFeatureList messageFeatureList = this.inputMessageFeatures.get(operationName);
227         return FeatureListUtil.mergeList(operationFeatureList, messageFeatureList, features);
228 
229     }
230 
231     public @NotNull WebServiceFeatureList getOutputMessageFeatures(@NotNull final QName operationName) {
232         final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName);
233         final WebServiceFeatureList messageFeatureList = this.outputMessageFeatures.get(operationName);
234         return FeatureListUtil.mergeList(operationFeatureList, messageFeatureList, features);
235     }
236 
237     public @NotNull WebServiceFeatureList getFaultMessageFeatures(@NotNull final QName operationName,
238             @NotNull final QName messageName) {
239         final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName);
240         final WebServiceFeatureList messageFeatureList = this.faultMessageFeatures.get(
241                 new MessageKey(operationName, messageName));
242         return FeatureListUtil.mergeList(operationFeatureList, messageFeatureList, features);
243     }
244 
245     public void setOperationFeatures(@NotNull final QName operationName, WebServiceFeature... newFeatures) {
246         if (newFeatures != null) {
247             WebServiceFeatureList featureList = operationFeatures.get(operationName);
248             if (featureList == null) {
249                 featureList = new WebServiceFeatureList();
250             }
251             for (WebServiceFeature f : newFeatures) {
252                 featureList.add(f);
253             }
254             operationFeatures.put(operationName, featureList);
255         }
256     }
257 
258     public void setInputMessageFeatures(@NotNull final QName operationName, WebServiceFeature... newFeatures) {
259         if (newFeatures != null) {
260             WebServiceFeatureList featureList = inputMessageFeatures.get(operationName);
261             if (featureList == null) {
262                 featureList = new WebServiceFeatureList();
263             }
264             for (WebServiceFeature f : newFeatures) {
265                 featureList.add(f);
266             }
267             inputMessageFeatures.put(operationName, featureList);
268         }
269     }
270 
271     public void setOutputMessageFeatures(@NotNull final QName operationName, WebServiceFeature... newFeatures) {
272         if (newFeatures != null) {
273             WebServiceFeatureList featureList = outputMessageFeatures.get(operationName);
274             if (featureList == null) {
275                 featureList = new WebServiceFeatureList();
276             }
277             for (WebServiceFeature f : newFeatures) {
278                 featureList.add(f);
279             }
280             outputMessageFeatures.put(operationName, featureList);
281         }
282     }
283 
284     public void setFaultMessageFeatures(@NotNull final QName operationName, @NotNull final QName messageName, WebServiceFeature... newFeatures) {
285         if (newFeatures != null) {
286             final MessageKey key = new MessageKey(operationName, messageName);
287             WebServiceFeatureList featureList = faultMessageFeatures.get(key);
288             if (featureList == null) {
289                 featureList = new WebServiceFeatureList();
290             }
291             for (WebServiceFeature f : newFeatures) {
292                 featureList.add(f);
293             }
294             faultMessageFeatures.put(key, featureList);
295         }
296     }
297 
298     public synchronized @NotNull com.oracle.webservices.internal.api.message.MessageContextFactory getMessageContextFactory () {
299         if (messageContextFactory == null) {
300             messageContextFactory = MessageContextFactory.createFactory(getFeatures().toArray());
301         }
302         return messageContextFactory;
303     }
304 
305     /**
306      * Experimental: Identify messages based on the name of the message and the
307      * operation that uses this message.
308      */
309     protected static class MessageKey {
310 
311         final private QName operationName;
312         final private QName messageName;
313 
314         public MessageKey(final QName operationName, final QName messageName) {
315             this.operationName = operationName;
316             this.messageName = messageName;
317         }
318 
319         @Override
320         public int hashCode() {
321             final int hashFirst = this.operationName != null ? this.operationName.hashCode() : 0;
322             final int hashSecond = this.messageName != null ? this.messageName.hashCode() : 0;
323 
324             return (hashFirst + hashSecond) * hashSecond + hashFirst;
325         }
326 
327         @Override
328         public boolean equals(Object obj) {
329             if (obj == null) {
330                 return false;
331             }
332             if (getClass() != obj.getClass()) {
333                 return false;
334             }
335             final MessageKey other = (MessageKey) obj;
336             if (this.operationName != other.operationName && (this.operationName == null || !this.operationName.equals(other.operationName))) {
337                 return false;
338             }
339             if (this.messageName != other.messageName && (this.messageName == null || !this.messageName.equals(other.messageName))) {
340                 return false;
341             }
342             return true;
343         }
344 
345         @Override
346         public String toString() {
347            return "(" + this.operationName + ", " + this.messageName + ")";
348         }
349 
350     }
351 
352 }