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;
018    
019    import java.lang.reflect.Method;
020    import java.rmi.AccessException;
021    import java.rmi.MarshalException;
022    import java.rmi.NoSuchObjectException;
023    import java.rmi.Remote;
024    import java.rmi.RemoteException;
025    import javax.transaction.InvalidTransactionException;
026    import javax.transaction.TransactionRequiredException;
027    import javax.transaction.TransactionRolledbackException;
028    
029    import net.sf.cglib.proxy.Callback;
030    import net.sf.cglib.proxy.CallbackFilter;
031    import net.sf.cglib.proxy.Enhancer;
032    import net.sf.cglib.proxy.MethodInterceptor;
033    import net.sf.cglib.proxy.MethodProxy;
034    import net.sf.cglib.proxy.NoOp;
035    import org.apache.commons.logging.Log;
036    import org.apache.commons.logging.LogFactory;
037    import org.omg.CORBA.INVALID_TRANSACTION;
038    import org.omg.CORBA.MARSHAL;
039    import org.omg.CORBA.NO_PERMISSION;
040    import org.omg.CORBA.OBJECT_NOT_EXIST;
041    import org.omg.CORBA.TRANSACTION_REQUIRED;
042    import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
043    import org.omg.CORBA.UNKNOWN;
044    
045    
046    /**
047     * @version $Revision: 465108 $ $Date: 2006-10-17 17:23:40 -0700 (Tue, 17 Oct 2006) $
048     */
049    public class AdapterProxyFactory {
050    
051        private final static Log log = LogFactory.getLog(AdapterProxyFactory.class);
052        private final static AdapterMethodInterceptor interceptor = new AdapterMethodInterceptor();
053        private final Enhancer enhancer;
054    
055        public AdapterProxyFactory(Class clientInterface) {
056            this(clientInterface, clientInterface.getClassLoader());
057        }
058    
059        public AdapterProxyFactory(Class clientInterface, ClassLoader classLoader) {
060            this(new Class[]{clientInterface}, classLoader);
061        }
062    
063    
064        public AdapterProxyFactory(Class[] clientInterfaces, ClassLoader classLoader) {
065            assert clientInterfaces != null;
066            assert areAllInterfaces(clientInterfaces);
067    
068            enhancer = new Enhancer();
069            enhancer.setClassLoader(classLoader);
070            enhancer.setSuperclass(AdapterDelegate.class);
071            enhancer.setInterfaces(clientInterfaces);
072            enhancer.setCallbackTypes(new Class[]{NoOp.class, MethodInterceptor.class});
073            enhancer.setCallbackFilter(FILTER);
074            enhancer.setUseFactory(false);
075        }
076    
077        private static boolean areAllInterfaces(Class[] clientInterfaces) {
078            for (int i = 0; i < clientInterfaces.length; i++) {
079                if (clientInterfaces[i] == null || !clientInterfaces[i].isInterface()) {
080                    return false;
081                }
082            }
083            return true;
084        }
085    
086        public Object create(Remote delegate, ClassLoader classLoader) {
087            return create(new Class[]{Remote.class, ClassLoader.class}, new Object[]{delegate, classLoader});
088        }
089    
090        public synchronized Object create(Class[] types, Object[] arguments) {
091            enhancer.setCallbacks(new Callback[]{NoOp.INSTANCE, interceptor});
092            return enhancer.create(types, arguments);
093        }
094    
095        private final static class AdapterMethodInterceptor implements MethodInterceptor {
096    
097            public final Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
098                ClassLoader savedCL = Thread.currentThread().getContextClassLoader();
099                try {
100                    AdapterDelegate delegate = (AdapterDelegate) o;
101                    Thread.currentThread().setContextClassLoader(delegate.getClassLoader());
102    
103                    if (log.isDebugEnabled()) log.debug("Calling " + method.getName());
104    
105                    return methodProxy.invoke(delegate.getDelegate(), args);
106                } catch (TransactionRolledbackException e) {
107                    log.debug("TransactionRolledbackException", e);
108                    throw new TRANSACTION_ROLLEDBACK(e.toString()).initCause(e);
109                } catch (TransactionRequiredException e) {
110                    log.debug("TransactionRequiredException", e);
111                    throw new TRANSACTION_REQUIRED(e.toString()).initCause(e);
112                } catch (InvalidTransactionException e) {
113                    log.debug("InvalidTransactionException", e);
114                    throw new INVALID_TRANSACTION(e.toString()).initCause(e);
115                } catch (NoSuchObjectException e) {
116                    log.debug("NoSuchObjectException", e);
117                    throw new OBJECT_NOT_EXIST(e.toString()).initCause(e);
118                } catch (AccessException e) {
119                    log.debug("AccessException", e);
120                    throw new NO_PERMISSION(e.toString()).initCause(e);
121                } catch (MarshalException e) {
122                    log.debug("MarshalException", e);
123                    throw new MARSHAL(e.toString()).initCause(e);
124                } catch (RemoteException e) {
125                    log.debug("RemoteException", e);
126                    throw new UNKNOWN(e.toString()).initCause(e);
127                } finally {
128                    Thread.currentThread().setContextClassLoader(savedCL);
129                }
130            }
131        }
132    
133        private static final CallbackFilter FILTER = new CallbackFilter() {
134            public int accept(Method method) {
135                if (method.getName().equals("finalize") &&
136                    method.getParameterTypes().length == 0 &&
137                    method.getReturnType() == Void.TYPE) {
138                    return 0;
139                }
140                return 1;
141            }
142        };
143    }
144