/*
* 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.tuscany.sca.binding.ejb.corba;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import javax.ejb.EJBObject;
import javax.rmi.CORBA.Stub;
import javax.rmi.CORBA.Util;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.portable.ApplicationException;
import org.omg.CORBA.portable.RemarshalException;
import org.omg.CORBA.portable.ServantObject;
import org.omg.CORBA_2_3.portable.InputStream;
import org.omg.CORBA_2_3.portable.OutputStream;
/**
* @version $Revision: 665774 $ $Date: 2008-06-09 18:05:18 +0100 (Mon, 09 Jun 2008) $
*/
public class StubMethodInterceptor implements MethodInterceptor {
private static final Method ISIDENTICAL;
static {
try {
ISIDENTICAL = EJBObject.class.getMethod("isIdentical", new Class[]{EJBObject.class});
} catch (NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
private final Class type;
private final Map operations;
public StubMethodInterceptor(Class type) {
this.type = type;
this.operations = Collections.unmodifiableMap(org.apache.tuscany.sca.binding.ejb.corba.Java2IDLUtil.mapMethodToOperation(type));
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Stub stub = (Stub) proxy;
// handle is identical in stub to avoid unnecessary round trip
if (method.equals(ISIDENTICAL)) {
org.omg.CORBA.Object otherObject = (org.omg.CORBA.Object) args[0];
return new Boolean(stub._is_equivalent(otherObject));
}
// get the operation name object
String operationName = (String) operations.get(method);
if (operationName == null) {
throw new IllegalStateException("Unknown method: " + method);
}
while (true) {
// if this is a stub to a remote object we invoke over the wire
if (!Util.isLocal(stub)) {
InputStream in = null;
try {
// create the request output stream
OutputStream out = (OutputStream) stub._request(operationName, true);
// write the arguments
Class[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class parameterType = parameterTypes[i];
org.apache.tuscany.sca.binding.ejb.corba.Java2IDLUtil.writeObject(parameterType, args[i], out);
}
// send the invocation
in = (InputStream) stub._invoke(out);
// read the result
Object result = org.apache.tuscany.sca.binding.ejb.corba.Java2IDLUtil.readObject(method.getReturnType(), in);
return result;
} catch (RemarshalException exception) {
continue;
} catch (ApplicationException exception) {
org.apache.tuscany.sca.binding.ejb.corba.Java2IDLUtil.throwException(method, (InputStream) exception.getInputStream());
} catch (SystemException e) {
throw Util.mapSystemException(e);
} finally {
stub._releaseReply(in);
}
} else {
// get the servant
ServantObject servantObject = stub._servant_preinvoke(operationName, type);
if (servantObject == null) {
continue;
}
try {
// copy the arguments
Object[] argsCopy = Util.copyObjects(args, stub._orb());
// invoke the servant
Object result = null;
try {
result = method.invoke(servantObject.servant, argsCopy);
} catch (InvocationTargetException e) {
if (e.getCause() != null) {
throw e.getCause();
}
throw e;
}
// copy the result
result = Util.copyObject(result, stub._orb());
return result;
} catch (Throwable throwable) {
// copy the exception
Throwable throwableCopy = (Throwable) Util.copyObject(throwable, stub._orb());
// if it is one of my exception rethrow it
Class[] exceptionTypes = method.getExceptionTypes();
for (int i = 0; i < exceptionTypes.length; i++) {
Class exceptionType = exceptionTypes[i];
if (exceptionType.isInstance(throwableCopy)) {
throw throwableCopy;
}
}
throw Util.wrapException(throwableCopy);
} finally {
stub._servant_postinvoke(servantObject);
}
}
}
}
}