package org.jboss.iiop.rmi;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.portable.IDLEntity;
import org.omg.CORBA.portable.ValueBase;
import java.rmi.Remote;
import java.io.Serializable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectStreamField;
import java.util.ArrayList;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Comparator;
import java.util.Map;
import java.util.WeakHashMap;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ValueAnalysis
extends ContainerAnalysis
{
private static final org.jboss.logging.Logger logger =
org.jboss.logging.Logger.getLogger(ValueAnalysis.class);
private static WorkCacheManager cache
= new WorkCacheManager(ValueAnalysis.class);
public static ValueAnalysis getValueAnalysis(Class cls)
throws RMIIIOPViolationException
{
return (ValueAnalysis)cache.getAnalysis(cls);
}
protected ValueAnalysis(Class cls)
{
super(cls);
logger.debug("ValueAnalysis(\""+cls.getName()+"\") entered.");
}
public String getIDLModuleName()
{
String result = super.getIDLModuleName();
Class clazz = getCls();
if (IDLEntity.class.isAssignableFrom(clazz) && ValueBase.class.isAssignableFrom(clazz) == false)
result = "::org::omg::boxedIDL" + result;
return result;
}
protected void doAnalyze()
throws RMIIIOPViolationException
{
super.doAnalyze();
if (cls == String.class)
throw new IllegalArgumentException(
"Cannot analyze java.lang.String here: It is a " +
"special case.");
if (cls == Class.class)
throw new IllegalArgumentException(
"Cannot analyze java.lang.Class here: It is a " +
"special case.");
if (Remote.class.isAssignableFrom(cls))
throw new RMIIIOPViolationException(
"Value type " + cls.getName() +
" cannot implement java.rmi.Remote.", "1.2.4");
if (cls.getName().indexOf('$') != -1)
throw new RMIIIOPNotImplementedException(
"Class " + cls.getName() + " has a '$', like " +
"proxies or inner classes.");
externalizable = Externalizable.class.isAssignableFrom(cls);
if (!externalizable) {
Field spf = null;
try {
spf = cls.getField("serialPersistentFields");
} catch (NoSuchFieldException ex) {
}
if (spf != null) { int mods = spf.getModifiers();
if (!Modifier.isFinal(mods) || !Modifier.isStatic(mods) ||
!Modifier.isPrivate(mods))
spf = null; }
if (spf != null) { Class type = spf.getType();
if (type.isArray()) {
type = type.getComponentType();
if (type != ObjectStreamField.class)
spf = null; } else
spf = null; }
if (spf != null) {
try {
serialPersistentFields = (ObjectStreamField[])spf.get(null);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Unexpected IllegalException: " +
ex.toString());
}
for (int i = 0; i < fields.length; ++i) {
if (fields[i] == spf) {
f_flags[i] |= F_SPFFIELD;
break;
}
}
}
Method wo = null;
try {
wo = cls.getMethod("writeObject",
new Class[] {java.io.OutputStream[].class} );
} catch (NoSuchMethodException ex) {
}
if (wo != null) { if (wo.getReturnType() != Void.TYPE)
wo = null; }
if (wo != null) { int mods = spf.getModifiers();
if (!Modifier.isPrivate(mods))
wo = null; }
if (wo != null) { Class[] paramTypes = wo.getParameterTypes();
if (paramTypes.length != 1)
wo = null; else if (paramTypes[0] != java.io.OutputStream.class)
wo = null; }
if (wo != null) {
hasWriteObjectMethod = true;
for (int i = 0; i < methods.length; ++i) {
if (methods[i] == wo) {
m_flags[i] |= M_WRITEOBJECT;
break;
}
}
}
}
SortedSet m = new TreeSet(new ValueMemberComparator());
logger.debug("ValueAnalysis(\""+cls.getName()+"\"): " +
"fields.length="+fields.length);
for (int i = 0; i < fields.length; ++i) {
logger.debug("ValueAnalysis(\""+cls.getName()+"\"): " +
"Considering field["+i+"] \"" + fields[i].getName() +
"\"" + " f_flags=" + f_flags[i]);
if (f_flags[i] != 0)
continue;
int mods = fields[i].getModifiers();
logger.debug("ValueAnalysis(\""+cls.getName()+"\"): mods=" + mods);
if (Modifier.isStatic(mods) || Modifier.isTransient(mods))
continue;
ValueMemberAnalysis vma;
vma = new ValueMemberAnalysis(fields[i].getName(),
fields[i].getType(),
Modifier.isPublic(mods));
m.add(vma);
}
members = new ValueMemberAnalysis[m.size()];
members = (ValueMemberAnalysis[])m.toArray(members);
logger.debug("ValueAnalysis(\""+cls.getName()+"\") value member count: "
+ members.length);
Class superClass = cls.getSuperclass();
if (superClass == java.lang.Object.class)
superClass = null;
if (superClass == null)
superAnalysis = null;
else {
logger.debug("ValueAnalysis(\""+cls.getName()+"\"): superclass: " +
superClass.getName());
superAnalysis = getValueAnalysis(superClass);
}
if (!Serializable.class.isAssignableFrom(cls))
abstractValue = true;
fixupCaseNames();
logger.debug("ValueAnalysis(\""+cls.getName()+"\") done.");
}
public ValueAnalysis getSuperAnalysis()
{
return superAnalysis;
}
public boolean isAbstractValue()
{
return abstractValue;
}
public boolean isCustom()
{
return externalizable || hasWriteObjectMethod;
}
public boolean isExternalizable()
{
return externalizable;
}
public ValueMemberAnalysis[] getMembers()
{
return (ValueMemberAnalysis[])members.clone();
}
protected void analyzeAttributes()
throws RMIIIOPViolationException
{
attributes = new AttributeAnalysis[0];
}
protected ArrayList getContainedEntries()
{
ArrayList ret = new ArrayList(constants.length +
attributes.length +
members.length);
for (int i = 0; i < constants.length; ++i)
ret.add(constants[i]);
for (int i = 0; i < attributes.length; ++i)
ret.add(attributes[i]);
for (int i = 0; i < members.length; ++i)
ret.add(members[i]);
return ret;
}
ValueAnalysis superAnalysis;
private boolean abstractValue = false;
private boolean externalizable = false;
private boolean hasWriteObjectMethod = false;
private ObjectStreamField[] serialPersistentFields;
private ValueMemberAnalysis[] members;
private static class ValueMemberComparator
implements Comparator
{
public int compare(Object o1, Object o2)
{
if (o1 == o2)
return 0;
ValueMemberAnalysis m1 = (ValueMemberAnalysis)o1;
ValueMemberAnalysis m2 = (ValueMemberAnalysis)o2;
boolean p1 = m1.getCls().isPrimitive();
boolean p2 = m2.getCls().isPrimitive();
if (p1 && !p2)
return -1;
if (!p1 && p2)
return 1;
return m1.getJavaName().compareTo(m2.getJavaName());
}
}
}