blob: f6b08eab1a50636010544cd895287c5cb0d82b03 [file] [log] [blame]
/*
* 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 com.sun.corba.se.impl.presentation.rmi ;
import java.io.Serializable ;
import java.io.Externalizable ;
import javax.rmi.PortableRemoteObject ;
import javax.rmi.CORBA.Util ;
import java.rmi.RemoteException ;
import java.rmi.UnexpectedException ;
import org.omg.CORBA.UserException ;
import org.omg.CORBA_2_3.portable.InputStream ;
import org.omg.CORBA_2_3.portable.OutputStream ;
import org.omg.CORBA.portable.ApplicationException ;
import java.lang.reflect.Method ;
import com.sun.corba.se.spi.logging.CORBALogDomains ;
import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
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 ) ;
}
}