/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openejb.server.axis.client; import net.sf.cglib.core.Signature; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.NoOp; import net.sf.cglib.reflect.FastClass; import net.sf.cglib.reflect.FastConstructor; import org.apache.axis.AxisEngine; import org.apache.axis.Constants; import org.apache.axis.client.Service; import org.apache.axis.constants.Use; import org.apache.axis.description.TypeDesc; import org.apache.axis.encoding.TypeMapping; import org.apache.axis.encoding.TypeMappingRegistry; import org.apache.axis.encoding.ser.SimpleDeserializerFactory; import org.apache.axis.encoding.ser.SimpleSerializerFactory; import org.apache.axis.handlers.HandlerInfoChainFactory; import org.apache.openejb.server.ServerRuntimeException; import javax.xml.namespace.QName; import javax.xml.rpc.ServiceException; import javax.xml.rpc.handler.HandlerChain; import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.rmi.Remote; import java.util.Iterator; import java.util.List; public class SeiFactoryImpl implements SeiFactory { private final QName serviceName; private final QName portQName; private final String serviceEndpointClassName; private final OperationInfo[] operationInfos; private FastConstructor constructor; private Object serviceImpl; private final List typeInfo; private final URL location; private final List handlerInfos; private final String credentialsName; private HandlerInfoChainFactory handlerInfoChainFactory; private OperationInfo[] sortedOperationInfos; private Class serviceEndpointClass; public SeiFactoryImpl(QName serviceName, String portName, String serviceEndpointClassName, OperationInfo[] operationInfos, List typeInfo, URL location, List handlerInfos, String credentialsName) { this.serviceName = serviceName; this.portQName = new QName("", portName); this.serviceEndpointClassName = serviceEndpointClassName; this.operationInfos = operationInfos; this.typeInfo = typeInfo; this.location = location; this.handlerInfos = handlerInfos; this.credentialsName = credentialsName; } void initialize(Object serviceImpl, ClassLoader classLoader) throws ClassNotFoundException { this.serviceImpl = serviceImpl; Class serviceEndpointBaseClass = classLoader.loadClass(serviceEndpointClassName); serviceEndpointClass = enhanceServiceEndpointInterface(serviceEndpointBaseClass, classLoader); Class[] constructorTypes = new Class[]{classLoader.loadClass(GenericServiceEndpoint.class.getName())}; this.constructor = FastClass.create(serviceEndpointClass).getConstructor(constructorTypes); this.handlerInfoChainFactory = new HandlerInfoChainFactory(handlerInfos); sortedOperationInfos = new OperationInfo[FastClass.create(serviceEndpointClass).getMaxIndex() + 1]; String encodingStyle = ""; for (int i = 0; i < operationInfos.length; i++) { OperationInfo operationInfo = operationInfos[i]; Signature signature = operationInfo.getSignature(); MethodProxy methodProxy = MethodProxy.find(serviceEndpointClass, signature); if (methodProxy == null) { throw new ServerRuntimeException("No method proxy for operationInfo " + signature); } int index = methodProxy.getSuperIndex(); sortedOperationInfos[index] = operationInfo; if (operationInfo.getOperationDesc().getUse() == Use.ENCODED) { encodingStyle = org.apache.axis.Constants.URI_SOAP11_ENC; } } //register our type descriptors Service service = ((ServiceImpl) serviceImpl).getService(); AxisEngine axisEngine = service.getEngine(); TypeMappingRegistry typeMappingRegistry = axisEngine.getTypeMappingRegistry(); TypeMapping typeMapping = typeMappingRegistry.getOrMakeTypeMapping(encodingStyle); typeMapping.register(BigInteger.class, Constants.XSD_UNSIGNEDLONG, new SimpleSerializerFactory(BigInteger.class, Constants.XSD_UNSIGNEDLONG), new SimpleDeserializerFactory(BigInteger.class, Constants.XSD_UNSIGNEDLONG)); typeMapping.register(URI.class, Constants.XSD_ANYURI, new SimpleSerializerFactory(URI.class, Constants.XSD_ANYURI), new SimpleDeserializerFactory(URI.class, Constants.XSD_ANYURI)); //It is essential that the types be registered before the typeInfos create the serializer/deserializers. for (Iterator iter = typeInfo.iterator(); iter.hasNext(); ) { TypeInfo info = (TypeInfo) iter.next(); TypeDesc.registerTypeDescForClass(info.getClazz(), info.buildTypeDesc()); } TypeInfo.register(typeInfo, typeMapping); } private Class enhanceServiceEndpointInterface(Class serviceEndpointInterface, ClassLoader classLoader) { Enhancer enhancer = new Enhancer(); enhancer.setClassLoader(classLoader); enhancer.setSuperclass(GenericServiceEndpointWrapper.class); enhancer.setInterfaces(new Class[]{serviceEndpointInterface}); enhancer.setCallbackFilter(new NoOverrideCallbackFilter(GenericServiceEndpointWrapper.class)); enhancer.setCallbackTypes(new Class[]{NoOp.class, MethodInterceptor.class}); enhancer.setUseFactory(false); enhancer.setUseCache(false); return enhancer.createClass(); } public Remote createServiceEndpoint() throws ServiceException { //TODO figure out why this can't be called in readResolve! // synchronized (this) { // if (!initialized) { // initialize(); // initialized = true; // } // } Service service = ((ServiceImpl) serviceImpl).getService(); GenericServiceEndpoint serviceEndpoint = new GenericServiceEndpoint(portQName, service, location); Callback callback = new ServiceEndpointMethodInterceptor(serviceEndpoint, sortedOperationInfos, credentialsName); Callback[] callbacks = new Callback[]{NoOp.INSTANCE, callback}; Enhancer.registerCallbacks(serviceEndpointClass, callbacks); try { return (Remote) constructor.newInstance(new Object[]{serviceEndpoint}); } catch (InvocationTargetException e) { throw (ServiceException) new ServiceException("Could not construct service instance", e.getTargetException()).initCause(e); } } public HandlerChain createHandlerChain() { return handlerInfoChainFactory.createHandlerChain(); } // private Object readResolve() throws ObjectStreamException { // SEIFactoryImpl seiFactory = new SEIFactoryImpl(serviceName, portQName.getLocalPart(), serviceEndpointClassName, operationInfos, typeInfo, location, handlerInfos, credentialsName); // seiFactory.initialize(); // return seiFactory; // } public OperationInfo[] getOperationInfos() { return operationInfos; } public QName getPortQName() { return portQName; } public QName getServiceName() { return serviceName; } public URL getWSDLDocumentLocation() { try { return new URL(location.toExternalForm() + "?wsdl"); } catch (MalformedURLException e) { return null; } } }