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.rmi.AccessException;
020    import java.rmi.MarshalException;
021    import java.rmi.NoSuchObjectException;
022    import java.rmi.Remote;
023    import java.rmi.RemoteException;
024    import java.lang.reflect.Proxy;
025    import java.lang.reflect.InvocationHandler;
026    import javax.rmi.CORBA.Stub;
027    import javax.rmi.CORBA.Tie;
028    import javax.rmi.CORBA.UtilDelegate;
029    import javax.rmi.CORBA.ValueHandler;
030    import javax.transaction.InvalidTransactionException;
031    import javax.transaction.TransactionRequiredException;
032    import javax.transaction.TransactionRolledbackException;
033    import javax.ejb.EJBHome;
034    import javax.ejb.EJBObject;
035    
036    import org.apache.commons.logging.Log;
037    import org.apache.commons.logging.LogFactory;
038    import org.omg.CORBA.CompletionStatus;
039    import org.omg.CORBA.INVALID_TRANSACTION;
040    import org.omg.CORBA.MARSHAL;
041    import org.omg.CORBA.NO_PERMISSION;
042    import org.omg.CORBA.OBJECT_NOT_EXIST;
043    import org.omg.CORBA.ORB;
044    import org.omg.CORBA.SystemException;
045    import org.omg.CORBA.TRANSACTION_REQUIRED;
046    import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
047    import org.omg.CORBA.UNKNOWN;
048    import org.omg.CORBA.portable.InputStream;
049    import org.omg.CORBA.portable.OutputStream;
050    
051    import org.apache.geronimo.corba.AdapterWrapper;
052    import org.apache.geronimo.corba.CORBAException;
053    import org.apache.geronimo.corba.RefGenerator;
054    import org.apache.geronimo.corba.StandardServant;
055    import org.apache.openejb.InterfaceType;
056    import org.apache.openejb.BeanType;
057    import org.apache.openejb.core.ivm.BaseEjbProxyHandler;
058    import org.apache.openejb.core.CoreDeploymentInfo;
059    
060    /**
061     * @version $Revision: 451417 $ $Date: 2006-09-29 13:13:22 -0700 (Fri, 29 Sep 2006) $
062     */
063    public final class UtilDelegateImpl implements UtilDelegate {
064    
065        private final Log log = LogFactory.getLog(UtilDelegateImpl.class);
066        private final UtilDelegate delegate;
067        private static ClassLoader classLoader;
068    
069        private final static String DELEGATE_NAME = "org.apache.geronimo.corba.UtilDelegateClass";
070    
071        public UtilDelegateImpl() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
072            String value = System.getProperty(DELEGATE_NAME);
073            if (value == null) {
074                log.error("No delegate specfied via " + DELEGATE_NAME);
075                throw new IllegalStateException("The property " + DELEGATE_NAME + " must be defined!");
076            }
077    
078            if (log.isDebugEnabled()) log.debug("Set delegate " + value);
079            delegate = (UtilDelegate) Class.forName(value).newInstance();
080        }
081    
082        static void setClassLoader(ClassLoader classLoader) {
083            UtilDelegateImpl.classLoader = classLoader;
084        }
085    
086        public void unexportObject(Remote target) throws NoSuchObjectException {
087            delegate.unexportObject(target);
088        }
089    
090        public boolean isLocal(Stub stub) throws RemoteException {
091            return delegate.isLocal(stub);
092        }
093    
094        public ValueHandler createValueHandler() {
095            return delegate.createValueHandler();
096        }
097    
098        public Object readAny(InputStream in) {
099            return delegate.readAny(in);
100        }
101    
102        public void writeAbstractObject(OutputStream out, Object obj) {
103            delegate.writeAbstractObject(out, obj);
104        }
105    
106        public void writeAny(OutputStream out, Object obj) {
107            delegate.writeAny(out, obj);
108        }
109    
110        public void writeRemoteObject(OutputStream out, Object obj) {
111            try {
112                if (obj instanceof Tie && ((Tie) obj).getTarget() instanceof Proxy) {
113                    obj = ((Tie) obj).getTarget();
114                }
115                if (obj instanceof Proxy) {
116                    obj = convertEJBToCORBAObject((Proxy) obj);
117                }
118                if (obj instanceof StandardServant) {
119                    StandardServant servant = (StandardServant) obj;
120                    InterfaceType servantType = servant.getInterfaceType();
121                    String deploymentId = servant.getEjbDeployment().getDeploymentId();
122                    try {
123                        RefGenerator refGenerator = AdapterWrapper.getRefGenerator(deploymentId);
124                        if (refGenerator == null) {
125                            throw new MARSHAL("Could not find RefGenerator for deployment id: " + deploymentId);
126                        }
127                        if (InterfaceType.EJB_HOME == servantType) {
128                            obj = refGenerator.genHomeReference();
129                        } else if (InterfaceType.EJB_OBJECT == servantType) {
130                            obj = refGenerator.genObjectReference(servant.getPrimaryKey());
131                        } else {
132                            log.error("Encountered unknown local invocation handler of type " + servantType + ":" + deploymentId);
133                            throw new MARSHAL("Internal server error while marshaling the reply", 0, CompletionStatus.COMPLETED_YES);
134                        }
135                    } catch (CORBAException e) {
136                        log.error("Encountered unknown local invocation handler of type " + servantType + ":" + deploymentId);
137                        throw (MARSHAL)new MARSHAL("Internal server error while marshaling the reply", 0, CompletionStatus.COMPLETED_YES).initCause(e);
138                    }
139                }
140                delegate.writeRemoteObject(out, obj);
141            } catch (Throwable e) {
142                log.error("Received unexpected exception while marshaling an object reference:", e);
143                throw (MARSHAL)new MARSHAL("Internal server error while marshaling the reply", 0, CompletionStatus.COMPLETED_YES).initCause(e);
144            }
145        }
146    
147        public String getCodebase(Class clz) {
148            return delegate.getCodebase(clz);
149        }
150    
151        public void registerTarget(Tie tie, Remote target) {
152            delegate.registerTarget(tie, target);
153        }
154    
155        public RemoteException wrapException(Throwable obj) {
156            return delegate.wrapException(obj);
157        }
158    
159        public RemoteException mapSystemException(SystemException ex) {
160            if (ex instanceof TRANSACTION_ROLLEDBACK) {
161                TransactionRolledbackException transactionRolledbackException = new TransactionRolledbackException(ex.getMessage());
162                transactionRolledbackException.detail = ex;
163                return transactionRolledbackException;
164            }
165            if (ex instanceof TRANSACTION_REQUIRED) {
166                TransactionRequiredException transactionRequiredException = new TransactionRequiredException(ex.getMessage());
167                transactionRequiredException.detail = ex;
168                return transactionRequiredException;
169            }
170            if (ex instanceof INVALID_TRANSACTION) {
171                InvalidTransactionException invalidTransactionException = new InvalidTransactionException(ex.getMessage());
172                invalidTransactionException.detail = ex;
173                return invalidTransactionException;
174            }
175            if (ex instanceof OBJECT_NOT_EXIST) {
176                NoSuchObjectException noSuchObjectException = new NoSuchObjectException(ex.getMessage());
177                noSuchObjectException.detail = ex;
178                return noSuchObjectException;
179            }
180            if (ex instanceof NO_PERMISSION) {
181                return new AccessException(ex.getMessage(), ex);
182            }
183            if (ex instanceof MARSHAL) {
184                return new MarshalException(ex.getMessage(), ex);
185            }
186            if (ex instanceof UNKNOWN) {
187                return new RemoteException(ex.getMessage(), ex);
188            }
189            return delegate.mapSystemException(ex);
190        }
191    
192        public Tie getTie(Remote target) {
193            return delegate.getTie(target);
194        }
195    
196        public Object copyObject(Object obj, ORB orb) throws RemoteException {
197            return delegate.copyObject(obj, orb);
198        }
199    
200        public Object[] copyObjects(Object[] obj, ORB orb) throws RemoteException {
201            return delegate.copyObjects(obj, orb);
202        }
203    
204        public Class loadClass(String className, String remoteCodebase, ClassLoader loader) throws ClassNotFoundException {
205            if (log.isDebugEnabled()) log.debug("Load class: " + className + ", " + remoteCodebase + ", " + loader);
206    
207            Class result = null;
208            try {
209                result = delegate.loadClass(className, remoteCodebase, loader);
210            } catch (ClassNotFoundException e) {
211                if (log.isDebugEnabled()) log.debug("Unable to load class from delegate");
212            }
213            if (result == null && classLoader != null) {
214                if (log.isDebugEnabled()) log.debug("Attempting to load " + className + " from the static class loader");
215    
216                try {
217                    result = classLoader.loadClass(className);
218                } catch (ClassNotFoundException e) {
219                    if (log.isDebugEnabled()) log.debug("Unable to load " + className + " from the static class loader");
220                    throw e;
221                }
222    
223                if (log.isDebugEnabled()) log.debug("result: " + (result == null ? "NULL" : result.getName()));
224            }
225    
226            return result;
227        }
228    
229        /**
230         * handle activation
231         */
232        private Object convertEJBToCORBAObject(Proxy proxy) {
233            InvocationHandler invocationHandler = Proxy.getInvocationHandler(proxy);
234            if (!(invocationHandler instanceof BaseEjbProxyHandler)) {
235                return proxy;
236            }
237    
238            BaseEjbProxyHandler ejbProxyHandler = (BaseEjbProxyHandler) invocationHandler;
239            CoreDeploymentInfo deploymentInfo = ejbProxyHandler.getDeploymentInfo();
240            String deploymentId = (String) deploymentInfo.getDeploymentID();
241            try {
242                RefGenerator refGenerator = AdapterWrapper.getRefGenerator(deploymentId);
243                if (refGenerator == null) {
244                    throw new MARSHAL("Could not find RefGenerator for deployment id: " +deploymentId);
245                }
246                if (proxy instanceof EJBHome) {
247                    return refGenerator.genHomeReference();
248                } else if (proxy instanceof EJBObject) {
249                    Object primaryKey = null;
250                    if (deploymentInfo.getComponentType() != BeanType.STATELESS) {
251                        EJBObject ejbObject = (EJBObject) proxy;
252                        primaryKey = ejbObject.getPrimaryKey();
253                    }
254                    return refGenerator.genObjectReference(primaryKey);
255                } else {
256                    log.error("Encountered unknown local invocation handler of type " + proxy.getClass().getSuperclass() + ":" + deploymentId);
257                    throw new MARSHAL("Internal server error while marshaling the reply", 0, CompletionStatus.COMPLETED_YES);
258                }
259            } catch (CORBAException e) {
260                log.error("Encountered unknown local invocation handler of type " + proxy.getClass().getSuperclass() + ":" + deploymentId);
261                throw (MARSHAL)new MARSHAL("Encountered unknown local invocation handler of type " + proxy.getClass().getSuperclass() + ":" + deploymentId, 0, CompletionStatus.COMPLETED_YES).initCause(e);
262            } catch (RemoteException e) {
263                log.error("Unable to get primary key from bean from bean of type " + proxy.getClass().getSuperclass() + ":" + deploymentId);
264                throw (MARSHAL)new MARSHAL("Unable to get primary key from bean from bean of type " + proxy.getClass().getSuperclass() + ":" + deploymentId, 0, CompletionStatus.COMPLETED_YES).initCause(e);
265            }
266        }
267    }