001 /** 002 * 003 * Copyright 2003-2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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.axis.client; 018 019 import java.io.Serializable; 020 import java.lang.reflect.InvocationTargetException; 021 import java.math.BigInteger; 022 import java.net.MalformedURLException; 023 import java.net.URI; 024 import java.net.URL; 025 import java.rmi.Remote; 026 import java.util.Iterator; 027 import java.util.List; 028 029 import javax.xml.namespace.QName; 030 import javax.xml.rpc.ServiceException; 031 import javax.xml.rpc.handler.HandlerChain; 032 033 import net.sf.cglib.core.Signature; 034 import net.sf.cglib.proxy.Callback; 035 import net.sf.cglib.proxy.Enhancer; 036 import net.sf.cglib.proxy.MethodInterceptor; 037 import net.sf.cglib.proxy.MethodProxy; 038 import net.sf.cglib.proxy.NoOp; 039 import net.sf.cglib.reflect.FastClass; 040 import net.sf.cglib.reflect.FastConstructor; 041 import org.apache.axis.AxisEngine; 042 import org.apache.axis.Constants; 043 import org.apache.axis.client.Service; 044 import org.apache.axis.constants.Use; 045 import org.apache.axis.description.TypeDesc; 046 import org.apache.axis.encoding.TypeMapping; 047 import org.apache.axis.encoding.TypeMappingRegistry; 048 import org.apache.axis.encoding.ser.SimpleDeserializerFactory; 049 import org.apache.axis.encoding.ser.SimpleSerializerFactory; 050 import org.apache.axis.handlers.HandlerInfoChainFactory; 051 052 /** 053 * @version $Rev: 394442 $ $Date: 2006-04-16 01:08:12 -0700 (Sun, 16 Apr 2006) $ 054 */ 055 public class SEIFactoryImpl implements SEIFactory, Serializable { 056 057 private final QName serviceName; 058 private final QName portQName; 059 private final String serviceEndpointClassName; 060 private final OperationInfo[] operationInfos; 061 private transient FastConstructor constructor; 062 private Object serviceImpl; 063 private final List typeInfo; 064 private final URL location; 065 private final List handlerInfos; 066 private final String credentialsName; 067 private transient HandlerInfoChainFactory handlerInfoChainFactory; 068 private transient OperationInfo[] sortedOperationInfos; 069 private Class serviceEndpointClass; 070 071 public SEIFactoryImpl(QName serviceName, String portName, String serviceEndpointClassName, OperationInfo[] operationInfos, List typeInfo, URL location, List handlerInfos, String credentialsName) { 072 this.serviceName = serviceName; 073 this.portQName = new QName("", portName); 074 this.serviceEndpointClassName = serviceEndpointClassName; 075 this.operationInfos = operationInfos; 076 this.typeInfo = typeInfo; 077 this.location = location; 078 this.handlerInfos = handlerInfos; 079 this.credentialsName = credentialsName; 080 } 081 082 void initialize(Object serviceImpl, ClassLoader classLoader) throws ClassNotFoundException { 083 this.serviceImpl = serviceImpl; 084 Class serviceEndpointBaseClass = classLoader.loadClass(serviceEndpointClassName); 085 serviceEndpointClass = enhanceServiceEndpointInterface(serviceEndpointBaseClass, classLoader); 086 Class[] constructorTypes = new Class[]{classLoader.loadClass(GenericServiceEndpoint.class.getName())}; 087 this.constructor = FastClass.create(serviceEndpointClass).getConstructor(constructorTypes); 088 this.handlerInfoChainFactory = new HandlerInfoChainFactory(handlerInfos); 089 sortedOperationInfos = new OperationInfo[FastClass.create(serviceEndpointClass).getMaxIndex() + 1]; 090 String encodingStyle = ""; 091 for (int i = 0; i < operationInfos.length; i++) { 092 OperationInfo operationInfo = operationInfos[i]; 093 Signature signature = operationInfo.getSignature(); 094 MethodProxy methodProxy = MethodProxy.find(serviceEndpointClass, signature); 095 if (methodProxy == null) { 096 throw new RuntimeException("No method proxy for operationInfo " + signature); 097 } 098 int index = methodProxy.getSuperIndex(); 099 sortedOperationInfos[index] = operationInfo; 100 if (operationInfo.getOperationDesc().getUse() == Use.ENCODED) { 101 encodingStyle = org.apache.axis.Constants.URI_SOAP11_ENC; 102 } 103 } 104 //register our type descriptors 105 Service service = ((ServiceImpl) serviceImpl).getService(); 106 AxisEngine axisEngine = service.getEngine(); 107 TypeMappingRegistry typeMappingRegistry = axisEngine.getTypeMappingRegistry(); 108 TypeMapping typeMapping = typeMappingRegistry.getOrMakeTypeMapping(encodingStyle); 109 typeMapping.register(BigInteger.class, 110 Constants.XSD_UNSIGNEDLONG, 111 new SimpleSerializerFactory(BigInteger.class, Constants.XSD_UNSIGNEDLONG), 112 new SimpleDeserializerFactory(BigInteger.class, Constants.XSD_UNSIGNEDLONG)); 113 typeMapping.register(URI.class, 114 Constants.XSD_ANYURI, 115 new SimpleSerializerFactory(URI.class, Constants.XSD_ANYURI), 116 new SimpleDeserializerFactory(URI.class, Constants.XSD_ANYURI)); 117 //It is essential that the types be registered before the typeInfos create the serializer/deserializers. 118 for (Iterator iter = typeInfo.iterator(); iter.hasNext();) { 119 TypeInfo info = (TypeInfo) iter.next(); 120 TypeDesc.registerTypeDescForClass(info.getClazz(), info.buildTypeDesc()); 121 } 122 TypeInfo.register(typeInfo, typeMapping); 123 } 124 125 private Class enhanceServiceEndpointInterface(Class serviceEndpointInterface, ClassLoader classLoader) { 126 Enhancer enhancer = new Enhancer(); 127 enhancer.setClassLoader(classLoader); 128 enhancer.setSuperclass(GenericServiceEndpointWrapper.class); 129 enhancer.setInterfaces(new Class[]{serviceEndpointInterface}); 130 enhancer.setCallbackFilter(new NoOverrideCallbackFilter(GenericServiceEndpointWrapper.class)); 131 enhancer.setCallbackTypes(new Class[]{NoOp.class, MethodInterceptor.class}); 132 enhancer.setUseFactory(false); 133 enhancer.setUseCache(false); 134 135 return enhancer.createClass(); 136 } 137 public Remote createServiceEndpoint() throws ServiceException { 138 //TODO figure out why this can't be called in readResolve! 139 // synchronized (this) { 140 // if (!initialized) { 141 // initialize(); 142 // initialized = true; 143 // } 144 // } 145 Service service = ((ServiceImpl) serviceImpl).getService(); 146 GenericServiceEndpoint serviceEndpoint = new GenericServiceEndpoint(portQName, service, location); 147 Callback callback = new ServiceEndpointMethodInterceptor(serviceEndpoint, sortedOperationInfos, credentialsName); 148 Callback[] callbacks = new Callback[]{SerializableNoOp.INSTANCE, callback}; 149 Enhancer.registerCallbacks(serviceEndpointClass, callbacks); 150 try { 151 return (Remote) constructor.newInstance(new Object[]{serviceEndpoint}); 152 } catch (InvocationTargetException e) { 153 e.getTargetException().printStackTrace(); 154 throw new ServiceException("Could not construct service instance", e.getTargetException()); 155 } 156 } 157 158 public HandlerChain createHandlerChain() { 159 return handlerInfoChainFactory.createHandlerChain(); 160 } 161 162 // private Object readResolve() throws ObjectStreamException { 163 // SEIFactoryImpl seiFactory = new SEIFactoryImpl(serviceName, portQName.getLocalPart(), serviceEndpointClassName, operationInfos, typeInfo, location, handlerInfos, credentialsName); 164 // seiFactory.initialize(); 165 // return seiFactory; 166 // } 167 168 public OperationInfo[] getOperationInfos() { 169 return operationInfos; 170 } 171 172 public QName getPortQName() { 173 return portQName; 174 } 175 176 public QName getServiceName() { 177 return serviceName; 178 } 179 180 public URL getWSDLDocumentLocation() { 181 try { 182 return new URL(location.toExternalForm() + "?wsdl"); 183 } catch (MalformedURLException e) { 184 return null; 185 } 186 } 187 }