1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/BindingImpl.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,404 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.ws.binding; 1.30 + 1.31 +import com.oracle.webservices.internal.api.message.MessageContextFactory; 1.32 +import com.sun.istack.internal.NotNull; 1.33 +import com.sun.istack.internal.Nullable; 1.34 +import com.sun.xml.internal.ws.api.BindingID; 1.35 +import com.sun.xml.internal.ws.api.SOAPVersion; 1.36 +import com.sun.xml.internal.ws.api.WSBinding; 1.37 +import com.sun.xml.internal.ws.api.addressing.AddressingVersion; 1.38 +import com.sun.xml.internal.ws.api.pipe.Codec; 1.39 +import com.sun.xml.internal.ws.client.HandlerConfiguration; 1.40 +import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature; 1.41 +import com.sun.xml.internal.ws.developer.BindingTypeFeature; 1.42 + 1.43 +import javax.activation.CommandInfo; 1.44 +import javax.activation.CommandMap; 1.45 +import javax.activation.MailcapCommandMap; 1.46 +import javax.xml.namespace.QName; 1.47 +import javax.xml.ws.Service; 1.48 +import javax.xml.ws.WebServiceFeature; 1.49 +import javax.xml.ws.soap.AddressingFeature; 1.50 +import javax.xml.ws.handler.Handler; 1.51 +import java.util.Collections; 1.52 +import java.util.HashMap; 1.53 +import java.util.HashSet; 1.54 +import java.util.List; 1.55 +import java.util.Set; 1.56 +import java.util.Map; 1.57 + 1.58 + 1.59 +/** 1.60 + * Instances are created by the service, which then 1.61 + * sets the handler chain on the binding impl. 1.62 + * 1.63 + * <p> 1.64 + * This class is made abstract as we don't see a situation when 1.65 + * a BindingImpl has much meaning without binding id. 1.66 + * IOW, for a specific binding there will be a class 1.67 + * extending BindingImpl, for example SOAPBindingImpl. 1.68 + * 1.69 + * <p> 1.70 + * The spi Binding interface extends Binding. 1.71 + * 1.72 + * @author WS Development Team 1.73 + */ 1.74 +public abstract class BindingImpl implements WSBinding { 1.75 + 1.76 + protected static final WebServiceFeature[] EMPTY_FEATURES = new WebServiceFeature[0]; 1.77 + 1.78 + //This is reset when ever Binding.setHandlerChain() or SOAPBinding.setRoles() is called. 1.79 + private HandlerConfiguration handlerConfig; 1.80 + private final Set<QName> addedHeaders = new HashSet<QName>(); 1.81 + private final Set<QName> knownHeaders = new HashSet<QName>(); 1.82 + private final Set<QName> unmodKnownHeaders = Collections.unmodifiableSet(knownHeaders); 1.83 + private final BindingID bindingId; 1.84 + // Features that are set(enabled/disabled) on the binding 1.85 + protected final WebServiceFeatureList features; 1.86 + // Features that are set(enabled/disabled) on the binding or an operation 1.87 + protected final Map<QName, WebServiceFeatureList> operationFeatures = new HashMap<QName, WebServiceFeatureList>(); 1.88 + // Features that are set(enabled/disabled) on the binding, an operation or an input message 1.89 + protected final Map<QName, WebServiceFeatureList> inputMessageFeatures = new HashMap<QName, WebServiceFeatureList>(); 1.90 + // Features that are set(enabled/disabled) on the binding, an operation or an output message 1.91 + protected final Map<QName, WebServiceFeatureList> outputMessageFeatures = new HashMap<QName, WebServiceFeatureList>(); 1.92 + // Features that are set(enabled/disabled) on the binding, an operation or a fault message 1.93 + protected final Map<MessageKey, WebServiceFeatureList> faultMessageFeatures = new HashMap<MessageKey, WebServiceFeatureList>(); 1.94 + 1.95 + protected javax.xml.ws.Service.Mode serviceMode = javax.xml.ws.Service.Mode.PAYLOAD; 1.96 + 1.97 + protected MessageContextFactory messageContextFactory; 1.98 + 1.99 + protected BindingImpl(BindingID bindingId, WebServiceFeature ... features) { 1.100 + this.bindingId = bindingId; 1.101 + handlerConfig = new HandlerConfiguration(Collections.<String>emptySet(), Collections.<Handler>emptyList()); 1.102 + if (handlerConfig.getHandlerKnownHeaders() != null) 1.103 + knownHeaders.addAll(handlerConfig.getHandlerKnownHeaders()); 1.104 + this.features = new WebServiceFeatureList(features); 1.105 + this.features.validate(); 1.106 + } 1.107 + 1.108 + public 1.109 + @NotNull 1.110 + List<Handler> getHandlerChain() { 1.111 + return handlerConfig.getHandlerChain(); 1.112 + } 1.113 + 1.114 + public HandlerConfiguration getHandlerConfig() { 1.115 + return handlerConfig; 1.116 + } 1.117 + 1.118 + protected void setHandlerConfig(HandlerConfiguration handlerConfig) { 1.119 + this.handlerConfig = handlerConfig; 1.120 + knownHeaders.clear(); 1.121 + knownHeaders.addAll(addedHeaders); 1.122 + if (handlerConfig != null && handlerConfig.getHandlerKnownHeaders() != null) 1.123 + knownHeaders.addAll(handlerConfig.getHandlerKnownHeaders()); 1.124 + } 1.125 + 1.126 + public void setMode(@NotNull Service.Mode mode) { 1.127 + this.serviceMode = mode; 1.128 + } 1.129 + 1.130 + public Set<QName> getKnownHeaders() { 1.131 + return unmodKnownHeaders; 1.132 + } 1.133 + 1.134 + public boolean addKnownHeader(QName headerQName) { 1.135 + addedHeaders.add(headerQName); 1.136 + return knownHeaders.add(headerQName); 1.137 + } 1.138 + 1.139 + public 1.140 + @NotNull 1.141 + BindingID getBindingId() { 1.142 + return bindingId; 1.143 + } 1.144 + 1.145 + public final SOAPVersion getSOAPVersion() { 1.146 + return bindingId.getSOAPVersion(); 1.147 + } 1.148 + 1.149 + public AddressingVersion getAddressingVersion() { 1.150 + AddressingVersion addressingVersion; 1.151 + if (features.isEnabled(AddressingFeature.class)) 1.152 + addressingVersion = AddressingVersion.W3C; 1.153 + else if (features.isEnabled(MemberSubmissionAddressingFeature.class)) 1.154 + addressingVersion = AddressingVersion.MEMBER; 1.155 + else 1.156 + addressingVersion = null; 1.157 + return addressingVersion; 1.158 + } 1.159 + 1.160 + @NotNull 1.161 + public final Codec createCodec() { 1.162 + 1.163 + // initialization from here should cover most of cases; 1.164 + // if not, it would be necessary to call 1.165 + // BindingImpl.initializeJavaActivationHandlers() 1.166 + // explicitly by programmer 1.167 + initializeJavaActivationHandlers(); 1.168 + 1.169 + return bindingId.createEncoder(this); 1.170 + } 1.171 + 1.172 + public static void initializeJavaActivationHandlers() { 1.173 + // DataHandler.writeTo() may search for DCH. So adding some default ones. 1.174 + try { 1.175 + CommandMap map = CommandMap.getDefaultCommandMap(); 1.176 + if (map instanceof MailcapCommandMap) { 1.177 + MailcapCommandMap mailMap = (MailcapCommandMap) map; 1.178 + 1.179 + // registering our DCH since javamail's DCH doesn't handle 1.180 + if (!cmdMapInitialized(mailMap)) { 1.181 + mailMap.addMailcap("text/xml;;x-java-content-handler=com.sun.xml.internal.ws.encoding.XmlDataContentHandler"); 1.182 + mailMap.addMailcap("application/xml;;x-java-content-handler=com.sun.xml.internal.ws.encoding.XmlDataContentHandler"); 1.183 + mailMap.addMailcap("image/*;;x-java-content-handler=com.sun.xml.internal.ws.encoding.ImageDataContentHandler"); 1.184 + mailMap.addMailcap("text/plain;;x-java-content-handler=com.sun.xml.internal.ws.encoding.StringDataContentHandler"); 1.185 + } 1.186 + } 1.187 + } catch (Throwable t) { 1.188 + // ignore the exception. 1.189 + } 1.190 + } 1.191 + 1.192 + private static boolean cmdMapInitialized(MailcapCommandMap mailMap) { 1.193 + CommandInfo[] commands = mailMap.getAllCommands("text/xml"); 1.194 + if (commands == null || commands.length == 0) { 1.195 + return false; 1.196 + } 1.197 + 1.198 + // SAAJ RI implements it's own DataHandlers which can be used for JAX-WS too; 1.199 + // see com.sun.xml.internal.messaging.saaj.soap.AttachmentPartImpl#initializeJavaActivationHandlers 1.200 + // so if found any of SAAJ or our own handler registered, we are ok; anyway using SAAJ directly here 1.201 + // is not good idea since we don't want standalone JAX-WS to depend on specific SAAJ impl. 1.202 + // This is also reason for duplication of Handler's code by JAX-WS 1.203 + String saajClassName = "com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler"; 1.204 + String jaxwsClassName = "com.sun.xml.internal.ws.encoding.XmlDataContentHandler"; 1.205 + for (CommandInfo command : commands) { 1.206 + String commandClass = command.getCommandClass(); 1.207 + if (saajClassName.equals(commandClass) || 1.208 + jaxwsClassName.equals(commandClass)) { 1.209 + return true; 1.210 + } 1.211 + } 1.212 + return false; 1.213 + } 1.214 + 1.215 + public static BindingImpl create(@NotNull BindingID bindingId) { 1.216 + if (bindingId.equals(BindingID.XML_HTTP)) 1.217 + return new HTTPBindingImpl(); 1.218 + else 1.219 + return new SOAPBindingImpl(bindingId); 1.220 + } 1.221 + 1.222 + public static BindingImpl create(@NotNull BindingID bindingId, WebServiceFeature[] features) { 1.223 + // Override the BindingID from the features 1.224 + for(WebServiceFeature feature : features) { 1.225 + if (feature instanceof BindingTypeFeature) { 1.226 + BindingTypeFeature f = (BindingTypeFeature)feature; 1.227 + bindingId = BindingID.parse(f.getBindingId()); 1.228 + } 1.229 + } 1.230 + if (bindingId.equals(BindingID.XML_HTTP)) 1.231 + return new HTTPBindingImpl(features); 1.232 + else 1.233 + return new SOAPBindingImpl(bindingId, features); 1.234 + } 1.235 + 1.236 + public static WSBinding getDefaultBinding() { 1.237 + return new SOAPBindingImpl(BindingID.SOAP11_HTTP); 1.238 + } 1.239 + 1.240 + public String getBindingID() { 1.241 + return bindingId.toString(); 1.242 + } 1.243 + 1.244 + public @Nullable <F extends WebServiceFeature> F getFeature(@NotNull Class<F> featureType){ 1.245 + return features.get(featureType); 1.246 + } 1.247 + 1.248 + public @Nullable <F extends WebServiceFeature> F getOperationFeature(@NotNull Class<F> featureType, 1.249 + @NotNull final QName operationName) { 1.250 + final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName); 1.251 + return FeatureListUtil.mergeFeature(featureType, operationFeatureList, features); 1.252 + } 1.253 + 1.254 + public boolean isFeatureEnabled(@NotNull Class<? extends WebServiceFeature> feature){ 1.255 + return features.isEnabled(feature); 1.256 + } 1.257 + 1.258 + public boolean isOperationFeatureEnabled(@NotNull Class<? extends WebServiceFeature> featureType, 1.259 + @NotNull final QName operationName) { 1.260 + final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName); 1.261 + return FeatureListUtil.isFeatureEnabled(featureType, operationFeatureList, features); 1.262 + } 1.263 + 1.264 + @NotNull 1.265 + public WebServiceFeatureList getFeatures() { 1.266 + //TODO scchen convert BindingID to WebServiceFeature[] 1.267 + if(!isFeatureEnabled(com.oracle.webservices.internal.api.EnvelopeStyleFeature.class)) { 1.268 + WebServiceFeature[] f = { getSOAPVersion().toFeature() }; 1.269 + features.mergeFeatures(f, false); 1.270 + } 1.271 + return features; 1.272 + } 1.273 + 1.274 + public @NotNull WebServiceFeatureList getOperationFeatures(@NotNull final QName operationName) { 1.275 + final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName); 1.276 + return FeatureListUtil.mergeList(operationFeatureList, features); 1.277 + } 1.278 + 1.279 + public @NotNull WebServiceFeatureList getInputMessageFeatures(@NotNull final QName operationName) { 1.280 + final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName); 1.281 + final WebServiceFeatureList messageFeatureList = this.inputMessageFeatures.get(operationName); 1.282 + return FeatureListUtil.mergeList(operationFeatureList, messageFeatureList, features); 1.283 + 1.284 + } 1.285 + 1.286 + public @NotNull WebServiceFeatureList getOutputMessageFeatures(@NotNull final QName operationName) { 1.287 + final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName); 1.288 + final WebServiceFeatureList messageFeatureList = this.outputMessageFeatures.get(operationName); 1.289 + return FeatureListUtil.mergeList(operationFeatureList, messageFeatureList, features); 1.290 + } 1.291 + 1.292 + public @NotNull WebServiceFeatureList getFaultMessageFeatures(@NotNull final QName operationName, 1.293 + @NotNull final QName messageName) { 1.294 + final WebServiceFeatureList operationFeatureList = this.operationFeatures.get(operationName); 1.295 + final WebServiceFeatureList messageFeatureList = this.faultMessageFeatures.get( 1.296 + new MessageKey(operationName, messageName)); 1.297 + return FeatureListUtil.mergeList(operationFeatureList, messageFeatureList, features); 1.298 + } 1.299 + 1.300 + public void setOperationFeatures(@NotNull final QName operationName, WebServiceFeature... newFeatures) { 1.301 + if (newFeatures != null) { 1.302 + WebServiceFeatureList featureList = operationFeatures.get(operationName); 1.303 + if (featureList == null) { 1.304 + featureList = new WebServiceFeatureList(); 1.305 + } 1.306 + for (WebServiceFeature f : newFeatures) { 1.307 + featureList.add(f); 1.308 + } 1.309 + operationFeatures.put(operationName, featureList); 1.310 + } 1.311 + } 1.312 + 1.313 + public void setInputMessageFeatures(@NotNull final QName operationName, WebServiceFeature... newFeatures) { 1.314 + if (newFeatures != null) { 1.315 + WebServiceFeatureList featureList = inputMessageFeatures.get(operationName); 1.316 + if (featureList == null) { 1.317 + featureList = new WebServiceFeatureList(); 1.318 + } 1.319 + for (WebServiceFeature f : newFeatures) { 1.320 + featureList.add(f); 1.321 + } 1.322 + inputMessageFeatures.put(operationName, featureList); 1.323 + } 1.324 + } 1.325 + 1.326 + public void setOutputMessageFeatures(@NotNull final QName operationName, WebServiceFeature... newFeatures) { 1.327 + if (newFeatures != null) { 1.328 + WebServiceFeatureList featureList = outputMessageFeatures.get(operationName); 1.329 + if (featureList == null) { 1.330 + featureList = new WebServiceFeatureList(); 1.331 + } 1.332 + for (WebServiceFeature f : newFeatures) { 1.333 + featureList.add(f); 1.334 + } 1.335 + outputMessageFeatures.put(operationName, featureList); 1.336 + } 1.337 + } 1.338 + 1.339 + public void setFaultMessageFeatures(@NotNull final QName operationName, @NotNull final QName messageName, WebServiceFeature... newFeatures) { 1.340 + if (newFeatures != null) { 1.341 + final MessageKey key = new MessageKey(operationName, messageName); 1.342 + WebServiceFeatureList featureList = faultMessageFeatures.get(key); 1.343 + if (featureList == null) { 1.344 + featureList = new WebServiceFeatureList(); 1.345 + } 1.346 + for (WebServiceFeature f : newFeatures) { 1.347 + featureList.add(f); 1.348 + } 1.349 + faultMessageFeatures.put(key, featureList); 1.350 + } 1.351 + } 1.352 + 1.353 + public synchronized @NotNull com.oracle.webservices.internal.api.message.MessageContextFactory getMessageContextFactory () { 1.354 + if (messageContextFactory == null) { 1.355 + messageContextFactory = MessageContextFactory.createFactory(getFeatures().toArray()); 1.356 + } 1.357 + return messageContextFactory; 1.358 + } 1.359 + 1.360 + /** 1.361 + * Experimental: Identify messages based on the name of the message and the 1.362 + * operation that uses this message. 1.363 + */ 1.364 + protected static class MessageKey { 1.365 + 1.366 + final private QName operationName; 1.367 + final private QName messageName; 1.368 + 1.369 + public MessageKey(final QName operationName, final QName messageName) { 1.370 + this.operationName = operationName; 1.371 + this.messageName = messageName; 1.372 + } 1.373 + 1.374 + @Override 1.375 + public int hashCode() { 1.376 + final int hashFirst = this.operationName != null ? this.operationName.hashCode() : 0; 1.377 + final int hashSecond = this.messageName != null ? this.messageName.hashCode() : 0; 1.378 + 1.379 + return (hashFirst + hashSecond) * hashSecond + hashFirst; 1.380 + } 1.381 + 1.382 + @Override 1.383 + public boolean equals(Object obj) { 1.384 + if (obj == null) { 1.385 + return false; 1.386 + } 1.387 + if (getClass() != obj.getClass()) { 1.388 + return false; 1.389 + } 1.390 + final MessageKey other = (MessageKey) obj; 1.391 + if (this.operationName != other.operationName && (this.operationName == null || !this.operationName.equals(other.operationName))) { 1.392 + return false; 1.393 + } 1.394 + if (this.messageName != other.messageName && (this.messageName == null || !this.messageName.equals(other.messageName))) { 1.395 + return false; 1.396 + } 1.397 + return true; 1.398 + } 1.399 + 1.400 + @Override 1.401 + public String toString() { 1.402 + return "(" + this.operationName + ", " + this.messageName + ")"; 1.403 + } 1.404 + 1.405 + } 1.406 + 1.407 +}