001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.jaxws.client;
018
019 import net.sf.cglib.proxy.MethodInterceptor;
020 import net.sf.cglib.proxy.MethodProxy;
021 import org.apache.commons.logging.Log;
022 import org.apache.commons.logging.LogFactory;
023 import org.apache.geronimo.jaxws.JAXWSUtils;
024 import org.apache.geronimo.security.ContextManager;
025 import org.apache.geronimo.security.jaas.NamedUsernamePasswordCredential;
026
027 import javax.security.auth.Subject;
028 import javax.xml.namespace.QName;
029 import javax.xml.ws.BindingProvider;
030 import javax.xml.ws.WebEndpoint;
031 import javax.xml.ws.soap.SOAPBinding;
032
033 import java.lang.reflect.Method;
034 import java.net.URL;
035 import java.util.Iterator;
036 import java.util.Map;
037 import java.util.Set;
038
039 public class PortMethodInterceptor implements MethodInterceptor {
040
041 private static final Log LOG = LogFactory.getLog(PortMethodInterceptor.class);
042
043 private Map<Object, EndpointInfo> seiInfoMap;
044
045 public PortMethodInterceptor(Map<Object, EndpointInfo> seiInfoMap) {
046 this.seiInfoMap = seiInfoMap;
047 }
048
049 public Object intercept(Object target, Method method, Object[] arguments, MethodProxy methodProxy) throws Throwable {
050 Object proxy = methodProxy.invokeSuper(target, arguments);
051
052 if (method.getName().equals("getPort")) {
053 // it's a generic getPort() method
054 if (arguments.length == 1) {
055 // getPort(Class) called - use SEI annotation
056 setProperties((BindingProvider)proxy, JAXWSUtils.getPortType((Class)arguments[0]));
057 } else if (arguments.length == 2) {
058 // getPort(QName, Class) called
059 if (arguments[0] == null) {
060 // port qname not specified - use SEI annotation
061 setProperties((BindingProvider)proxy, JAXWSUtils.getPortType((Class)arguments[1]));
062 } else {
063 // port qname specified
064 setProperties((BindingProvider)proxy, ((QName)arguments[0]).getLocalPart());
065 }
066 }
067 } else if (method.getName().startsWith("get")) {
068 // it's a generated get<PortName>() method
069 WebEndpoint endpoint = method.getAnnotation(WebEndpoint.class);
070 setProperties((BindingProvider)proxy, endpoint.name());
071 } else if (method.getName().equals("createDispatch")) {
072 // it's one of createDispatch() methods
073 setProperties((BindingProvider)proxy, ((QName)arguments[0]).getLocalPart());
074 }
075
076 return proxy;
077 }
078
079 private void setProperties(BindingProvider proxy, QName portType) {
080 if (portType == null) {
081 return;
082 }
083 EndpointInfo info = this.seiInfoMap.get(portType);
084 setProperties(proxy, info);
085 }
086
087 private void setProperties(BindingProvider proxy, String portName) {
088 if (portName == null) {
089 return;
090 }
091 EndpointInfo info = this.seiInfoMap.get(portName);
092 setProperties(proxy, info);
093 }
094
095 private void setProperties(BindingProvider proxy, EndpointInfo info) {
096 if (info == null) {
097 return;
098 }
099
100 // set mtom
101 boolean enableMTOM = info.isMTOMEnabled();
102 if (enableMTOM && proxy.getBinding() instanceof SOAPBinding) {
103 ((SOAPBinding)proxy.getBinding()).setMTOMEnabled(enableMTOM);
104 LOG.debug("Set mtom property: " + enableMTOM);
105 }
106
107 // set address
108 URL location = info.getLocation();
109 if (location != null) {
110 proxy.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, location.toString());
111 LOG.debug("Set address property: " + location);
112 }
113
114 // set credentials
115 String credentialsName = info.getCredentialsName();
116 if (credentialsName != null) {
117 Subject subject = ContextManager.getNextCaller();
118 if (subject == null) {
119 throw new IllegalStateException("Subject missing but authentication turned on");
120 } else {
121 Set creds = subject.getPrivateCredentials(NamedUsernamePasswordCredential.class);
122 boolean found = false;
123
124 for (Iterator iterator = creds.iterator(); iterator.hasNext();) {
125 NamedUsernamePasswordCredential namedUsernamePasswordCredential = (NamedUsernamePasswordCredential) iterator.next();
126 if (credentialsName.equals(namedUsernamePasswordCredential.getName())) {
127 proxy.getRequestContext().put(BindingProvider.USERNAME_PROPERTY,
128 namedUsernamePasswordCredential.getUsername());
129 proxy.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,
130 new String(namedUsernamePasswordCredential.getPassword()));
131 LOG.debug("Set username/password property: " + credentialsName);
132 found = true;
133 break;
134 }
135 }
136 if (!found) {
137 throw new IllegalStateException("no NamedUsernamePasswordCredential found for name " + credentialsName);
138 }
139 }
140 }
141 }
142 }