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