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 }