package org.jboss.iiop.rmi.marshal.strategy;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import org.omg.CORBA.UserException;
import org.omg.CORBA.portable.IDLEntity;
import org.omg.CORBA.portable.UnknownException;
import org.omg.CORBA_2_3.portable.InputStream;
import org.omg.CORBA_2_3.portable.OutputStream;
import org.jboss.iiop.rmi.ExceptionAnalysis;
import org.jboss.iiop.rmi.RMIIIOPViolationException;
import org.jboss.iiop.rmi.marshal.CDRStream;
import org.jboss.iiop.rmi.marshal.CDRStreamReader;
import org.jboss.iiop.rmi.marshal.CDRStreamWriter;
public class SkeletonStrategy
{
private CDRStreamReader[] paramReaders;
private Method m;
private ExceptionWriter[] excepWriters;
private CDRStreamWriter retvalWriter;
public SkeletonStrategy(Method m)
{
this.m = m;
Class[] paramTypes = m.getParameterTypes();
int len = paramTypes.length;
paramReaders = new CDRStreamReader[len];
for (int i = 0; i < len; i++) {
paramReaders[i] = CDRStream.readerFor(paramTypes[i]);
}
Class[] excepTypes = m.getExceptionTypes();
len = excepTypes.length;
int n = 0;
for (int i = 0; i < len; i++) {
if (!RemoteException.class.isAssignableFrom(excepTypes[i])) {
n++;
}
}
excepWriters = new ExceptionWriter[n];
int j = 0;
for (int i = 0; i < len; i++) {
if (!RemoteException.class.isAssignableFrom(excepTypes[i])) {
excepWriters[j++] = new ExceptionWriter(excepTypes[i]);
}
}
ExceptionWriter.arraysort(excepWriters);
retvalWriter = CDRStream.writerFor(m.getReturnType());
}
public Object[] readParams(InputStream in)
{
int len = paramReaders.length;
Object[] params = new Object[len];
for (int i = 0; i < len; i++ ) {
params[i] = paramReaders[i].read(in);
}
return params;
}
public Method getMethod()
{
return m;
}
public boolean isNonVoid()
{
return (retvalWriter != null);
}
public void writeRetval(OutputStream out, Object retVal)
{
retvalWriter.write(out, retVal);
}
public void writeException(OutputStream out, Exception e)
{
int len = excepWriters.length;
for (int i = 0; i < len; i++) {
if (excepWriters[i].getExceptionClass().isInstance(e)) {
excepWriters[i].write(out, e);
return;
}
}
throw new UnknownException(e);
}
private static class ExceptionWriter
implements CDRStreamWriter
{
private Class clz;
private java.lang.reflect.Method writeMethod = null;
private String reposId;
ExceptionWriter(Class clz)
{
this.clz = clz;
if (IDLEntity.class.isAssignableFrom(clz)
&& UserException.class.isAssignableFrom(clz)) {
String helperClassName = clz.getName() + "Helper";
try {
Class helperClass =
clz.getClassLoader().loadClass(helperClassName);
Class[] paramTypes =
{ org.omg.CORBA.portable.OutputStream.class, clz };
writeMethod = helperClass.getMethod("write", paramTypes);
}
catch (ClassNotFoundException e) {
throw new RuntimeException("Error loading class "
+ helperClassName + ": " + e);
}
catch (NoSuchMethodException e) {
throw new RuntimeException("No write method in helper class "
+ helperClassName + ": " + e);
}
}
else {
try {
this.reposId = ExceptionAnalysis.getExceptionAnalysis(clz)
.getExceptionRepositoryId();
}
catch (RMIIIOPViolationException e) {
throw new RuntimeException("Cannot obtain "
+ "exception repository id for "
+ clz.getName() + ":\n" + e);
}
}
}
Class getExceptionClass()
{
return clz;
}
public void write(OutputStream out, Object excep)
{
if (writeMethod != null) {
try {
writeMethod.invoke(null, new Object[] { out, excep });
}
catch (IllegalAccessException e) {
throw new RuntimeException("Internal error: " + e);
}
catch (java.lang.reflect.InvocationTargetException e) {
throw new RuntimeException("Exception marshaling IDLEntity: "
+ e.getTargetException());
}
}
else {
out.write_string(reposId);
out.write_value((Exception)excep, clz);
}
}
static void arraysort(ExceptionWriter[] a)
{
int len = a.length;
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (a[i].clz.isAssignableFrom(a[j].clz)) {
ExceptionWriter tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
}
}
}