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.corba.util;
018    
019    import java.lang.reflect.InvocationTargetException;
020    import java.lang.reflect.Method;
021    import java.util.Collections;
022    import java.util.Map;
023    
024    import javax.ejb.EJBObject;
025    import javax.rmi.CORBA.Util;
026    
027    import net.sf.cglib.proxy.MethodInterceptor;
028    import net.sf.cglib.proxy.MethodProxy;
029    import org.omg.CORBA.SystemException;
030    import org.omg.CORBA.portable.ApplicationException;
031    import org.omg.CORBA.portable.RemarshalException;
032    import org.omg.CORBA.portable.ServantObject;
033    import org.omg.CORBA_2_3.portable.InputStream;
034    import org.omg.CORBA_2_3.portable.OutputStream;
035    
036    /**
037     * @version $Revision: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
038     */
039    public class StubMethodInterceptor implements MethodInterceptor {
040        private static final Method ISIDENTICAL;
041    
042        static {
043            try {
044                ISIDENTICAL = EJBObject.class.getMethod("isIdentical", new Class[]{EJBObject.class});
045            } catch (NoSuchMethodException e) {
046                throw new ExceptionInInitializerError(e);
047            }
048        }
049    
050        private final Class type;
051        private final Map operations;
052    
053        public StubMethodInterceptor(Class type) {
054            this.type = type;
055            this.operations = Collections.unmodifiableMap(org.apache.geronimo.corba.util.Util.mapMethodToOperation(type));
056        }
057    
058        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
059            ClientContextHolderStub stub = (ClientContextHolderStub) proxy;
060    
061            // handle is identical in stub to avoid unnecessary round trip
062            if (method.equals(ISIDENTICAL)) {
063                org.omg.CORBA.Object otherObject = (org.omg.CORBA.Object) args[0];
064                return new Boolean(stub._is_equivalent(otherObject));
065            }
066    
067            // get the operation name object
068            String operationName = (String) operations.get(method);
069            if (operationName == null) {
070                throw new IllegalStateException("Unknown method: " + method);
071            }
072    
073            while (true) {
074                // if this is a stub to a remote object we invoke over the wire
075                if (!Util.isLocal(stub)) {
076    
077                    InputStream in = null;
078                    try {
079                        // create the request output stream
080                        OutputStream out = (OutputStream) stub._request(operationName, true);
081    
082                        // write the arguments
083                        Class[] parameterTypes = method.getParameterTypes();
084                        for (int i = 0; i < parameterTypes.length; i++) {
085                            Class parameterType = parameterTypes[i];
086                            org.apache.geronimo.corba.util.Util.writeObject(parameterType, args[i], out);
087                        }
088    
089                        // send the invocation
090                        in = (InputStream) stub._invoke(out);
091    
092                        // read the result
093                        Object result = org.apache.geronimo.corba.util.Util.readObject(method.getReturnType(), in);
094                        return result;
095                    } catch (RemarshalException exception) {
096                        continue;
097                    } catch (ApplicationException exception) {
098                        org.apache.geronimo.corba.util.Util.throwException(method, (InputStream) exception.getInputStream());
099                    } catch (SystemException e) {
100                        throw Util.mapSystemException(e);
101                    } finally {
102                        stub._releaseReply(in);
103                    }
104                } else {
105                    // get the servant
106                    ServantObject servantObject = stub._servant_preinvoke(operationName, type);
107                    if (servantObject == null) {
108                        continue;
109                    }
110    
111                    try {
112                        // copy the arguments
113                        Object[] argsCopy = Util.copyObjects(args, stub._orb());
114    
115                        // invoke the servant
116                        Object result = null;
117                        try {
118                            result = method.invoke(servantObject.servant, argsCopy);
119                        } catch (InvocationTargetException e) {
120                            if (e.getCause() != null) {
121                                throw e.getCause();
122                            }
123                            throw e;
124                        }
125    
126                        // copy the result
127                        result = Util.copyObject(result, stub._orb());
128    
129                        return result;
130                    } catch (Throwable throwable) {
131                        // copy the exception
132                        Throwable throwableCopy = (Throwable) Util.copyObject(throwable, stub._orb());
133    
134                        // if it is one of my exception rethrow it
135                        Class[] exceptionTypes = method.getExceptionTypes();
136                        for (int i = 0; i < exceptionTypes.length; i++) {
137                            Class exceptionType = exceptionTypes[i];
138                            if (exceptionType.isInstance(throwableCopy)) {
139                                throw throwableCopy;
140                            }
141                        }
142    
143                        throw Util.wrapException(throwableCopy);
144                    } finally {
145                        stub._servant_postinvoke(servantObject);
146                    }
147                }
148            }
149        }
150    }