001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.jaxws;
020:
021: import java.util.Hashtable;
022: import java.util.Map;
023:
024: import javax.xml.ws.Binding;
025: import javax.xml.ws.handler.HandlerResolver;
026: import org.apache.axis2.jaxws.binding.BindingUtils;
027: import org.apache.axis2.jaxws.binding.SOAPBinding;
028: import org.apache.axis2.jaxws.client.PropertyValidator;
029: import org.apache.axis2.jaxws.core.InvocationContext;
030: import org.apache.axis2.jaxws.core.MessageContext;
031: import org.apache.axis2.jaxws.description.EndpointDescription;
032: import org.apache.axis2.jaxws.handler.HandlerResolverImpl;
033: import org.apache.axis2.jaxws.i18n.Messages;
034: import org.apache.axis2.jaxws.spi.ServiceDelegate;
035: import org.apache.axis2.transport.http.HTTPConstants;
036:
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039:
040: public class BindingProvider implements
041: org.apache.axis2.jaxws.spi.BindingProvider {
042:
043: protected Map<String, Object> requestContext;
044:
045: protected Map<String, Object> responseContext;
046:
047: protected EndpointDescription endpointDesc;
048:
049: protected ServiceDelegate serviceDelegate;
050:
051: private Binding binding = null;
052: private static final Log log = LogFactory
053: .getLog(BindingProvider.class);
054:
055: public BindingProvider(ServiceDelegate svcDelegate,
056: EndpointDescription epDesc) {
057: endpointDesc = epDesc;
058: serviceDelegate = svcDelegate;
059:
060: initialize();
061: }
062:
063: /*
064: * Initialize any objects needed by the BindingProvider
065: */
066: private void initialize() {
067: requestContext = new ValidatingClientContext();
068: responseContext = new ValidatingClientContext();
069:
070: // Setting standard property defaults for the request context
071: requestContext.put(BindingProvider.SESSION_MAINTAIN_PROPERTY,
072: new Boolean(false));
073: requestContext.put(BindingProvider.SOAPACTION_USE_PROPERTY,
074: new Boolean(true));
075:
076: // Set the endpoint address
077: String endpointAddress = endpointDesc.getEndpointAddress();
078: if (endpointAddress != null) {
079: requestContext.put(
080: BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
081: endpointAddress);
082: }
083:
084: // JAXWS 9.2.1.1 requires that we go ahead and create the binding object
085: // so we can also set the handlerchain
086: if (binding == null) {
087: binding = BindingUtils.createBinding(endpointDesc);
088: if (log.isDebugEnabled()) {
089: log.debug("Lookign for Handler Resolver");
090: }
091: // TODO should we allow the ServiceDelegate to figure out the default handlerresolver? Probably yes, since a client app may look for one there.
092: HandlerResolver handlerResolver = null;
093: if (serviceDelegate.getHandlerResolver() != null) {
094: if (log.isDebugEnabled()) {
095: log.debug("Reading default Handler Resolver ");
096: }
097: handlerResolver = serviceDelegate.getHandlerResolver();
098: } else {
099: handlerResolver = new HandlerResolverImpl(endpointDesc
100: .getServiceDescription());
101: if (log.isDebugEnabled()) {
102: log
103: .debug("Creating new Handler Resolver using HandlerResolverImpl");
104: }
105: }
106: binding.setHandlerChain(handlerResolver
107: .getHandlerChain(endpointDesc.getPortInfo()));
108: }
109:
110: }
111:
112: public ServiceDelegate getServiceDelegate() {
113: return serviceDelegate;
114: }
115:
116: public EndpointDescription getEndpointDescription() {
117: return endpointDesc;
118: }
119:
120: public Binding getBinding() {
121: return binding;
122: }
123:
124: public void setBinding(Binding binding) {
125: this .binding = binding;
126: }
127:
128: public Map<String, Object> getRequestContext() {
129: return requestContext;
130: }
131:
132: public Map<String, Object> getResponseContext() {
133: return responseContext;
134: }
135:
136: /**
137: * Check for maintain session state enablement either in the
138: * MessageContext.isMaintainSession() or in the ServiceContext properties.
139: *
140: * @param mc
141: * @param ic
142: */
143: protected void checkMaintainSessionState(MessageContext mc,
144: InvocationContext ic) {
145: Map<String, Object> properties = ic.getServiceClient()
146: .getServiceContext().getProperties();
147: boolean bValue = false;
148:
149: if (properties != null
150: && properties
151: .containsKey(javax.xml.ws.BindingProvider.SESSION_MAINTAIN_PROPERTY)) {
152: bValue = (Boolean) properties
153: .get(javax.xml.ws.BindingProvider.SESSION_MAINTAIN_PROPERTY);
154: }
155: if (mc.isMaintainSession() || bValue == true) {
156: setupSessionContext(properties);
157: }
158: }
159:
160: /*
161: * Ensure that the next request context contains the session value returned
162: * from previous request
163: */
164: protected void setupSessionContext(Map<String, Object> properties) {
165: String sessionKey = null;
166: String sessionValue = null;
167:
168: if (properties == null) {
169: return;
170: }
171:
172: if (properties.containsKey(HTTPConstants.HEADER_LOCATION)) {
173: sessionKey = HTTPConstants.HEADER_LOCATION;
174: sessionValue = (String) properties.get(sessionKey);
175: if (sessionValue != null && !"".equals(sessionValue)) {
176: requestContext.put(
177: BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
178: sessionValue);
179: }
180: } else if (properties.containsKey(HTTPConstants.HEADER_COOKIE)) {
181: sessionKey = HTTPConstants.HEADER_COOKIE;
182: sessionValue = (String) properties.get(sessionKey);
183: if (sessionValue != null && !"".equals(sessionValue)) {
184: requestContext.put(HTTPConstants.COOKIE_STRING,
185: sessionValue);
186: }
187: } else if (properties.containsKey(HTTPConstants.HEADER_COOKIE2)) {
188: sessionKey = HTTPConstants.HEADER_COOKIE2;
189: sessionValue = (String) properties.get(sessionKey);
190: if (sessionValue != null && !"".equals(sessionValue)) {
191: requestContext.put(HTTPConstants.COOKIE_STRING,
192: sessionValue);
193: }
194: } else {
195: throw ExceptionFactory.makeWebServiceException(Messages
196: .getMessage("NoMaintainSessionProperty"));
197: }
198:
199: if (sessionValue == null) {
200: throw ExceptionFactory.makeWebServiceException(Messages
201: .getMessage("NullValueForMaintainSessionProperty",
202: sessionKey));
203: }
204: }
205:
206: /**
207: * Returns a boolean value representing whether or not a SOAPAction header should be sent with
208: * the request.
209: */
210: protected boolean useSoapAction() {
211: //TODO: Add some bit of validation for this property so that we know
212: // it is actually a Boolean and not a String.
213: Boolean use = (Boolean) requestContext
214: .get(BindingProvider.SOAPACTION_USE_PROPERTY);
215: if (use != null) {
216: if (use.booleanValue()) {
217: return true;
218: } else {
219: return false;
220: }
221: } else {
222: // If the value is not set, then just default to sending a SOAPAction
223: return true;
224: }
225: }
226:
227: /*
228: * An inner class used to validate properties as they are set by the client.
229: */
230: class ValidatingClientContext extends Hashtable<String, Object> {
231:
232: @Override
233: public synchronized Object put(String key, Object value) {
234: // super.put rightly throws a NullPointerException if key or value is null, so don't continue if that's the case
235: if (value == null)
236: return null;
237: if (PropertyValidator.validate(key, value)) {
238: return super .put(key, value);
239: } else {
240: throw ExceptionFactory.makeWebServiceException(Messages
241: .getMessage("invalidPropValue", key, value
242: .getClass().getName(),
243: PropertyValidator.getExpectedValue(key)
244: .getName()));
245: }
246: }
247: }
248: }
|