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 }