/* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package org.jboss.com.sun.corba.se.impl.presentation.rmi; import java.lang.reflect.Method; import java.rmi.RemoteException; import java.rmi.UnexpectedException; import org.jboss.com.sun.corba.se.impl.logging.ORBUtilSystemException; import org.jboss.com.sun.corba.se.spi.logging.CORBALogDomains; import org.omg.CORBA.UserException; import org.omg.CORBA.portable.ApplicationException; import org.omg.CORBA_2_3.portable.InputStream; import org.omg.CORBA_2_3.portable.OutputStream; public class ExceptionHandlerImpl implements ExceptionHandler { private ExceptionRW[] rws; private final ORBUtilSystemException wrapper; // ///////////////////////////////////////////////////////////////////////////// // ExceptionRW interface and implementations. // Used to read and write exceptions. // ///////////////////////////////////////////////////////////////////////////// public interface ExceptionRW { Class<?> getExceptionClass(); String getId(); void write(OutputStream os, Exception ex); Exception read(InputStream is); } public abstract class ExceptionRWBase implements ExceptionRW { private Class<?> cls; private String id; public ExceptionRWBase(Class<?> cls) { this.cls = cls; } public Class<?> getExceptionClass() { return cls; } public String getId() { return id; } void setId(String id) { this.id = id; } } public class ExceptionRWIDLImpl extends ExceptionRWBase { private Method readMethod; private Method writeMethod; public ExceptionRWIDLImpl(Class<?> cls) { super(cls); String helperName = cls.getName() + "Helper"; ClassLoader loader = cls.getClassLoader(); Class<?> helperClass; try { helperClass = Class.forName(helperName, true, loader); Method idMethod = helperClass.getDeclaredMethod("id", (Class[]) null); setId((String) idMethod.invoke(null, (Object[]) null)); } catch (Exception ex) { throw wrapper.badHelperIdMethod(ex, helperName); } try { Class<?>[] argTypes = new Class[]{org.omg.CORBA.portable.OutputStream.class, cls}; writeMethod = helperClass.getDeclaredMethod("write", argTypes); } catch (Exception ex) { throw wrapper.badHelperWriteMethod(ex, helperName); } try { Class<?>[] argTypes = new Class[]{org.omg.CORBA.portable.InputStream.class}; readMethod = helperClass.getDeclaredMethod("read", argTypes); } catch (Exception ex) { throw wrapper.badHelperReadMethod(ex, helperName); } } public void write(OutputStream os, Exception ex) { try { Object[] args = new Object[]{os, ex}; writeMethod.invoke(null, args); } catch (Exception exc) { throw wrapper.badHelperWriteMethod(exc, writeMethod.getDeclaringClass().getName()); } } public Exception read(InputStream is) { try { Object[] args = new Object[]{is}; return (Exception) readMethod.invoke(null, args); } catch (Exception ex) { throw wrapper.badHelperReadMethod(ex, readMethod.getDeclaringClass().getName()); } } } public class ExceptionRWRMIImpl extends ExceptionRWBase { public ExceptionRWRMIImpl(Class<?> cls) { super(cls); setId(IDLNameTranslatorImpl.getExceptionId(cls)); } public void write(OutputStream os, Exception ex) { os.write_string(getId()); os.write_value(ex, getExceptionClass()); } public Exception read(InputStream is) { is.read_string(); // read and ignore! return (Exception) is.read_value(getExceptionClass()); } } // ///////////////////////////////////////////////////////////////////////////// public ExceptionHandlerImpl(Class<?>[] exceptions) { wrapper = ORBUtilSystemException.get(CORBALogDomains.RPC_PRESENTATION); int count = 0; for (int ctr = 0; ctr < exceptions.length; ctr++) { Class<?> cls = exceptions[ctr]; if (!RemoteException.class.isAssignableFrom(cls)) count++; } rws = new ExceptionRW[count]; int index = 0; for (int ctr = 0; ctr < exceptions.length; ctr++) { Class<?> cls = exceptions[ctr]; if (!RemoteException.class.isAssignableFrom(cls)) { ExceptionRW erw = null; if (UserException.class.isAssignableFrom(cls)) erw = new ExceptionRWIDLImpl(cls); else erw = new ExceptionRWRMIImpl(cls); /* * The following check is not performed in order to maintain compatibility with rmic. See bug 4989312. * * // Check for duplicate repository ID String repositoryId = erw.getId() ; int duplicateIndex = * findDeclaredException( repositoryId ) ; if (duplicateIndex > 0) { ExceptionRW duprw = * rws[duplicateIndex] ; String firstClassName = erw.getExceptionClass().getName() ; String * secondClassName = duprw.getExceptionClass().getName() ; throw wrapper.duplicateExceptionRepositoryId( * firstClassName, secondClassName, repositoryId ) ; } */ rws[index++] = erw; } } } private int findDeclaredException(Class<?> cls) { for (int ctr = 0; ctr < rws.length; ctr++) { Class<?> next = rws[ctr].getExceptionClass(); if (next.isAssignableFrom(cls)) return ctr; } return -1; } private int findDeclaredException(String repositoryId) { for (int ctr = 0; ctr < rws.length; ctr++) { // This may occur when rws has not been fully // populated, in which case the search should just fail. if (rws[ctr] == null) return -1; String rid = rws[ctr].getId(); if (repositoryId.equals(rid)) return ctr; } return -1; } public boolean isDeclaredException(Class<?> cls) { return findDeclaredException(cls) >= 0; } public void writeException(OutputStream os, Exception ex) { int index = findDeclaredException(ex.getClass()); if (index < 0) throw wrapper.writeUndeclaredException(ex, ex.getClass().getName()); rws[index].write(os, ex); } public Exception readException(ApplicationException ae) { // Note that the exception ID is present in both ae // and in the input stream from ae. The exception // reader must actually read the exception ID from // the stream. InputStream is = (InputStream) ae.getInputStream(); String excName = ae.getId(); int index = findDeclaredException(excName); if (index < 0) { excName = is.read_string(); Exception res = new UnexpectedException(excName); res.initCause(ae); return res; } return rws[index].read(is); } // This is here just for the dynamicrmiiiop test public ExceptionRW getRMIExceptionRW(Class<?> cls) { return new ExceptionRWRMIImpl(cls); } }