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 018 package org.apache.geronimo.jaxws.client; 019 020 import org.apache.geronimo.naming.reference.SimpleReference; 021 import org.apache.geronimo.naming.reference.ClassLoaderAwareReference; 022 import org.apache.geronimo.naming.reference.KernelAwareReference; 023 import org.apache.geronimo.kernel.Kernel; 024 import org.apache.geronimo.gbean.AbstractName; 025 import org.apache.commons.logging.Log; 026 import org.apache.commons.logging.LogFactory; 027 028 import javax.naming.NamingException; 029 import javax.xml.ws.Service; 030 import javax.xml.ws.handler.HandlerResolver; 031 import javax.xml.namespace.QName; 032 import java.net.URL; 033 import java.net.MalformedURLException; 034 import java.net.URI; 035 import java.lang.reflect.InvocationTargetException; 036 import java.util.Map; 037 038 import net.sf.cglib.proxy.Callback; 039 import net.sf.cglib.proxy.NoOp; 040 import net.sf.cglib.proxy.Enhancer; 041 import net.sf.cglib.proxy.MethodInterceptor; 042 import net.sf.cglib.reflect.FastConstructor; 043 import net.sf.cglib.reflect.FastClass; 044 045 public abstract class JAXWSServiceReference extends SimpleReference implements ClassLoaderAwareReference, KernelAwareReference { 046 private static final Log LOG = LogFactory.getLog(JAXWSServiceReference.class); 047 private static final Class[] URL_SERVICE_NAME_CONSTRUCTOR = 048 new Class[] { URL.class, QName.class }; 049 050 protected String serviceClassName; 051 protected ClassLoader classLoader; 052 protected AbstractName moduleName; 053 protected URI wsdlURI; 054 protected QName serviceQName; 055 private Kernel kernel; 056 protected String handlerChainsXML; 057 protected Map<Object, EndpointInfo> seiInfoMap; 058 protected String referenceClassName; 059 060 protected Class enhancedServiceClass; 061 protected Callback[] methodInterceptors; 062 protected FastConstructor serviceConstructor; 063 064 public JAXWSServiceReference(String handlerChainsXML, Map<Object, EndpointInfo> seiInfoMap, AbstractName name, QName serviceQName, URI wsdlURI, String referenceClassName, String serviceClassName) { 065 this.handlerChainsXML = handlerChainsXML; 066 this.seiInfoMap = seiInfoMap; 067 this.moduleName = name; 068 this.serviceQName = serviceQName; 069 this.wsdlURI = wsdlURI; 070 this.referenceClassName = referenceClassName; 071 this.serviceClassName = serviceClassName; 072 } 073 074 public void setClassLoader(ClassLoader classLoader) { 075 this.classLoader = classLoader; 076 } 077 078 public void setKernel(Kernel kernel) { 079 this.kernel = kernel; 080 } 081 082 private Class loadClass(String name) throws NamingException { 083 try { 084 return this.classLoader.loadClass(name); 085 } catch (ClassNotFoundException e) { 086 NamingException exception = new NamingException( 087 "Count not load class " + name); 088 exception.initCause(e); 089 throw exception; 090 } 091 } 092 093 private URL getWsdlURL() { 094 if (this.wsdlURI == null) { 095 return null; 096 } 097 try { 098 return new URL(this.wsdlURI.toString()); 099 } catch (MalformedURLException e1) { 100 // not a URL, assume it's a local reference 101 try { 102 URL moduleBaseUrl = (URL) this.kernel.getAttribute( 103 this.moduleName, "configurationBaseUrl"); 104 return new URL(moduleBaseUrl.toString() + this.wsdlURI.toString()); 105 } catch (Exception e) { 106 URL wsdlURL = this.classLoader.getResource(this.wsdlURI.toString()); 107 if (wsdlURL == null) { 108 LOG.warn("Error obtaining WSDL: " + this.wsdlURI, e); 109 } 110 return wsdlURL; 111 } 112 } 113 } 114 115 private Class getReferenceClass() throws NamingException { 116 return (this.referenceClassName != null) ? loadClass(this.referenceClassName) : null; 117 } 118 119 public Object getContent() throws NamingException { 120 Service instance = null; 121 URL wsdlURL = getWsdlURL(); 122 123 Class serviceClass = loadClass(this.serviceClassName); 124 Class referenceClass = getReferenceClass(); 125 126 if (referenceClass != null && Service.class.isAssignableFrom(referenceClass)) { 127 serviceClass = referenceClass; 128 } 129 130 if (Service.class.equals(serviceClass)) { 131 serviceClass = GenericService.class; 132 } 133 134 instance = createServiceProxy(serviceClass, this.classLoader, this.serviceQName, wsdlURL); 135 136 HandlerResolver handlerResolver = getHandlerResolver(serviceClass); 137 if(handlerResolver != null) { 138 instance.setHandlerResolver(handlerResolver); 139 } 140 141 if (referenceClass != null && !Service.class.isAssignableFrom(referenceClass)) { 142 // do port lookup 143 return instance.getPort(referenceClass); 144 } else { 145 // return service 146 return instance; 147 } 148 } 149 150 protected abstract HandlerResolver getHandlerResolver(Class serviceClass); 151 152 protected PortMethodInterceptor getPortMethodInterceptor() { 153 return new PortMethodInterceptor(this.seiInfoMap); 154 } 155 156 private Service createServiceProxy(Class superClass, ClassLoader classLoader, QName serviceName, URL wsdlLocation) throws NamingException { 157 if (this.serviceConstructor == null) { 158 // create method interceptors 159 Callback callback = getPortMethodInterceptor(); 160 this.methodInterceptors = new Callback[] {NoOp.INSTANCE, callback}; 161 162 // create service class 163 Enhancer enhancer = new Enhancer(); 164 enhancer.setClassLoader(classLoader); 165 enhancer.setSuperclass(superClass); 166 enhancer.setCallbackFilter(new PortMethodFilter()); 167 enhancer.setCallbackTypes(new Class[] { NoOp.class, MethodInterceptor.class }); 168 enhancer.setUseFactory(false); 169 enhancer.setUseCache(false); 170 this.enhancedServiceClass = enhancer.createClass(); 171 172 // get constructor 173 this.serviceConstructor = 174 FastClass.create(this.enhancedServiceClass).getConstructor(URL_SERVICE_NAME_CONSTRUCTOR); 175 } 176 177 LOG.debug("Initializing service with: " + wsdlLocation + " " + serviceName); 178 179 // associate the method interceptors with the generated service class on the current thread 180 Enhancer.registerCallbacks(this.enhancedServiceClass, this.methodInterceptors); 181 182 Object[] arguments = new Object[] {wsdlLocation, serviceName}; 183 184 try { 185 return (Service)this.serviceConstructor.newInstance(arguments); 186 } catch (InvocationTargetException e) { 187 NamingException exception = new NamingException("Could not construct service proxy"); 188 exception.initCause(e.getTargetException()); 189 throw exception; 190 } 191 } 192 }