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.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: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
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 throw (ServiceException)new ServiceException("Could not construct service instance", e.getTargetException()).initCause(e);
154 }
155 }
156
157 public HandlerChain createHandlerChain() {
158 return handlerInfoChainFactory.createHandlerChain();
159 }
160
161 // private Object readResolve() throws ObjectStreamException {
162 // SEIFactoryImpl seiFactory = new SEIFactoryImpl(serviceName, portQName.getLocalPart(), serviceEndpointClassName, operationInfos, typeInfo, location, handlerInfos, credentialsName);
163 // seiFactory.initialize();
164 // return seiFactory;
165 // }
166
167 public OperationInfo[] getOperationInfos() {
168 return operationInfos;
169 }
170
171 public QName getPortQName() {
172 return portQName;
173 }
174
175 public QName getServiceName() {
176 return serviceName;
177 }
178
179 public URL getWSDLDocumentLocation() {
180 try {
181 return new URL(location.toExternalForm() + "?wsdl");
182 } catch (MalformedURLException e) {
183 return null;
184 }
185 }
186 }