blob: 20cec8d7b30710ca10ec3ee647fd31c1cdebec98 [file] [log] [blame]
/*
* Copyright (c) 1999, 2013, 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.
*/
/*
* Licensed Materials - Property of IBM
* RMI-IIOP v1.0
* Copyright IBM Corp. 1998 1999 All Rights Reserved
*
*/
package com.sun.corba.se.impl.io;
import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
import com.sun.org.omg.CORBA.OperationDescription;
import com.sun.org.omg.CORBA.AttributeDescription;
import org.omg.CORBA.ValueMember;
import com.sun.org.omg.CORBA.Initializer;
import org.omg.CORBA.IDLType;
import com.sun.org.omg.CORBA._IDLTypeStub;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TypeCodePackage.*;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.TCKind;
import java.lang.reflect.*;
import com.sun.corba.se.impl.util.RepositoryId;
import java.util.*;
import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.ValueHandler;
/**
* Holds utility methods for converting from ObjectStreamClass to
* FullValueDescription and generating typecodes from ObjectStreamClass.
**/
public class ValueUtility {
public static final short PRIVATE_MEMBER = 0;
public static final short PUBLIC_MEMBER = 1;
private static final String primitiveConstants[] = {
null, // tk_null 0
null, // tk_void 1
"S", // tk_short 2
"I", // tk_long 3
"S", // tk_ushort 4
"I", // tk_ulong 5
"F", // tk_float 6
"D", // tk_double 7
"Z", // tk_boolean 8
"C", // tk_char 9
"B", // tk_octet 10
null, // tk_any 11
null, // tk_typecode 12
null, // tk_principal 13
null, // tk_objref 14
null, // tk_struct 15
null, // tk_union 16
null, // tk_enum 17
null, // tk_string 18
null, // tk_sequence 19
null, // tk_array 20
null, // tk_alias 21
null, // tk_except 22
"J", // tk_longlong 23
"J", // tk_ulonglong 24
"D", // tk_longdouble 25
"C", // tk_wchar 26
null, // tk_wstring 27
null, // tk_fixed 28
null, // tk_value 29
null, // tk_value_box 30
null, // tk_native 31
null, // tk_abstract_interface 32
};
static {
sun.corba.SharedSecrets.setJavaCorbaAccess(new sun.corba.JavaCorbaAccess() {
public ValueHandlerImpl newValueHandlerImpl() {
return ValueHandlerImpl.getInstance();
}
public Class<?> loadClass(String className) throws ClassNotFoundException {
if (Thread.currentThread().getContextClassLoader() != null) {
return Thread.currentThread().getContextClassLoader().
loadClass(className);
} else {
return ClassLoader.getSystemClassLoader().loadClass(className);
}
}
});
}
public static String getSignature(ValueMember member)
throws ClassNotFoundException {
// REVISIT. Can the type be something that is
// non-primitive yet not a value_box, value, or objref?
// If so, should use ObjectStreamClass or throw
// exception.
if (member.type.kind().value() == TCKind._tk_value_box ||
member.type.kind().value() == TCKind._tk_value ||
member.type.kind().value() == TCKind._tk_objref) {
Class c = RepositoryId.cache.getId(member.id).getClassFromType();
return ObjectStreamClass.getSignature(c);
} else {
return primitiveConstants[member.type.kind().value()];
}
}
public static FullValueDescription translate(ORB orb, ObjectStreamClass osc, ValueHandler vh){
// Create FullValueDescription
FullValueDescription result = new FullValueDescription();
Class className = osc.forClass();
ValueHandlerImpl vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
String repId = vhandler.createForAnyType(className);
// Set FVD name
result.name = vhandler.getUnqualifiedName(repId);
if (result.name == null)
result.name = "";
// Set FVD id _REVISIT_ : Manglings
result.id = vhandler.getRMIRepositoryID(className);
if (result.id == null)
result.id = "";
// Set FVD is_abstract
result.is_abstract = ObjectStreamClassCorbaExt.isAbstractInterface(className);
// Set FVD is_custom
result.is_custom = osc.hasWriteObject() || osc.isExternalizable();
// Set FVD defined_in _REVISIT_ : Manglings
result.defined_in = vhandler.getDefinedInId(repId);
if (result.defined_in == null)
result.defined_in = "";
// Set FVD version
result.version = vhandler.getSerialVersionUID(repId);
if (result.version == null)
result.version = "";
// Skip FVD operations - N/A
result.operations = new OperationDescription[0];
// Skip FVD attributed - N/A
result.attributes = new AttributeDescription[0];
// Set FVD members
// Maps classes to repositoryIDs strings. This is used to detect recursive types.
IdentityKeyValueStack createdIDs = new IdentityKeyValueStack();
// Stores all types created for resolving indirect types at the end.
result.members = translateMembers(orb, osc, vh, createdIDs);
// Skip FVD initializers - N/A
result.initializers = new Initializer[0];
Class interfaces[] = osc.forClass().getInterfaces();
int abstractCount = 0;
// Skip FVD supported_interfaces
result.supported_interfaces = new String[interfaces.length];
for (int interfaceIndex = 0; interfaceIndex < interfaces.length;
interfaceIndex++) {
result.supported_interfaces[interfaceIndex] =
vhandler.createForAnyType(interfaces[interfaceIndex]);
if ((!(java.rmi.Remote.class.isAssignableFrom(interfaces[interfaceIndex]))) ||
(!Modifier.isPublic(interfaces[interfaceIndex].getModifiers())))
abstractCount++;
}
// Skip FVD abstract_base_values - N/A
result.abstract_base_values = new String[abstractCount];
for (int interfaceIndex = 0; interfaceIndex < interfaces.length;
interfaceIndex++) {
if ((!(java.rmi.Remote.class.isAssignableFrom(interfaces[interfaceIndex]))) ||
(!Modifier.isPublic(interfaces[interfaceIndex].getModifiers())))
result.abstract_base_values[interfaceIndex] =
vhandler.createForAnyType(interfaces[interfaceIndex]);
}
result.is_truncatable = false;
// Set FVD base_value
Class superClass = osc.forClass().getSuperclass();
if (java.io.Serializable.class.isAssignableFrom(superClass))
result.base_value = vhandler.getRMIRepositoryID(superClass);
else
result.base_value = "";
// Set FVD type
//result.type = createTypeCodeForClass(orb, osc.forClass());
result.type = orb.get_primitive_tc(TCKind.tk_value); //11638
return result;
}
private static ValueMember[] translateMembers (ORB orb,
ObjectStreamClass osc,
ValueHandler vh,
IdentityKeyValueStack createdIDs)
{
ValueHandlerImpl vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
ObjectStreamField fields[] = osc.getFields();
int fieldsLength = fields.length;
ValueMember[] members = new ValueMember[fieldsLength];
// Note : fields come out of ObjectStreamClass in correct order for
// writing. So, we will create the same order in the members array.
for (int i = 0; i < fieldsLength; i++) {
String valRepId = vhandler.getRMIRepositoryID(fields[i].getClazz());
members[i] = new ValueMember();
members[i].name = fields[i].getName();
members[i].id = valRepId; // _REVISIT_ : Manglings
members[i].defined_in = vhandler.getDefinedInId(valRepId);// _REVISIT_ : Manglings
members[i].version = "1.0";
members[i].type_def = new _IDLTypeStub(); // _REVISIT_ : IDLType implementation missing
if (fields[i].getField() == null) {
// When using serialPersistentFields, the class may
// no longer have an actual Field that corresponds
// to one of the items. The Java to IDL spec
// ptc-00-01-06 1.3.5.6 says that the IDL field
// should be private in this case.
members[i].access = PRIVATE_MEMBER;
} else {
int m = fields[i].getField().getModifiers();
if (Modifier.isPublic(m))
members[i].access = PUBLIC_MEMBER;
else
members[i].access = PRIVATE_MEMBER;
}
switch (fields[i].getTypeCode()) {
case 'B':
members[i].type = orb.get_primitive_tc(TCKind.tk_octet); //11638
break;
case 'C':
members[i].type
= orb.get_primitive_tc(vhandler.getJavaCharTCKind()); // 11638
break;
case 'F':
members[i].type = orb.get_primitive_tc(TCKind.tk_float); //11638
break;
case 'D' :
members[i].type = orb.get_primitive_tc(TCKind.tk_double); //11638
break;
case 'I':
members[i].type = orb.get_primitive_tc(TCKind.tk_long); //11638
break;
case 'J':
members[i].type = orb.get_primitive_tc(TCKind.tk_longlong); //11638
break;
case 'S':
members[i].type = orb.get_primitive_tc(TCKind.tk_short); //11638
break;
case 'Z':
members[i].type = orb.get_primitive_tc(TCKind.tk_boolean); //11638
break;
// case '[':
// members[i].type = orb.get_primitive_tc(TCKind.tk_value_box); //11638
// members[i].id = RepositoryId.createForAnyType(fields[i].getType());
// break;
default:
members[i].type = createTypeCodeForClassInternal(orb, fields[i].getClazz(), vhandler,
createdIDs);
members[i].id = vhandler.createForAnyType(fields[i].getType());
break;
} // end switch
} // end for loop
return members;
}
private static boolean exists(String str, String strs[]){
for (int i = 0; i < strs.length; i++)
if (str.equals(strs[i]))
return true;
return false;
}
public static boolean isAssignableFrom(String clzRepositoryId, FullValueDescription type,
com.sun.org.omg.SendingContext.CodeBase sender){
if (exists(clzRepositoryId, type.supported_interfaces))
return true;
if (clzRepositoryId.equals(type.id))
return true;
if ((type.base_value != null) &&
(!type.base_value.equals(""))) {
FullValueDescription parent = sender.meta(type.base_value);
return isAssignableFrom(clzRepositoryId, parent, sender);
}
return false;
}
public static TypeCode createTypeCodeForClass (ORB orb, java.lang.Class c, ValueHandler vh) {
// Maps classes to repositoryIDs strings. This is used to detect recursive types.
IdentityKeyValueStack createdIDs = new IdentityKeyValueStack();
// Stores all types created for resolving indirect types at the end.
TypeCode tc = createTypeCodeForClassInternal(orb, c, vh, createdIDs);
return tc;
}
private static TypeCode createTypeCodeForClassInternal (ORB orb,
java.lang.Class c,
ValueHandler vh,
IdentityKeyValueStack createdIDs)
{
// This wrapper method is the protection against infinite recursion.
TypeCode tc = null;
String id = (String)createdIDs.get(c);
if (id != null) {
return orb.create_recursive_tc(id);
} else {
id = vh.getRMIRepositoryID(c);
if (id == null) id = "";
// cache the rep id BEFORE creating a new typecode.
// so that recursive tc can look up the rep id.
createdIDs.push(c, id);
tc = createTypeCodeInternal(orb, c, vh, id, createdIDs);
createdIDs.pop();
return tc;
}
}
// Maintains a stack of key-value pairs. Compares elements using == operator.
private static class IdentityKeyValueStack {
private static class KeyValuePair {
Object key;
Object value;
KeyValuePair(Object key, Object value) {
this.key = key;
this.value = value;
}
boolean equals(KeyValuePair pair) {
return pair.key == this.key;
}
}
Stack pairs = null;
Object get(Object key) {
if (pairs == null) {
return null;
}
for (Iterator i = pairs.iterator(); i.hasNext();) {
KeyValuePair pair = (KeyValuePair)i.next();
if (pair.key == key) {
return pair.value;
}
}
return null;
}
void push(Object key, Object value) {
if (pairs == null) {
pairs = new Stack();
}
pairs.push(new KeyValuePair(key, value));
}
void pop() {
pairs.pop();
}
}
private static TypeCode createTypeCodeInternal (ORB orb,
java.lang.Class c,
ValueHandler vh,
String id,
IdentityKeyValueStack createdIDs)
{
if ( c.isArray() ) {
// Arrays - may recurse for multi-dimensional arrays
Class componentClass = c.getComponentType();
TypeCode embeddedType;
if ( componentClass.isPrimitive() ){
embeddedType
= ValueUtility.getPrimitiveTypeCodeForClass(orb,
componentClass,
vh);
} else {
embeddedType = createTypeCodeForClassInternal(orb, componentClass, vh,
createdIDs);
}
TypeCode t = orb.create_sequence_tc (0, embeddedType);
return orb.create_value_box_tc (id, "Sequence", t);
} else if ( c == java.lang.String.class ) {
// Strings
TypeCode t = orb.create_string_tc (0);
return orb.create_value_box_tc (id, "StringValue", t);
} else if (java.rmi.Remote.class.isAssignableFrom(c)) {
return orb.get_primitive_tc(TCKind.tk_objref);
} else if (org.omg.CORBA.Object.class.isAssignableFrom(c)) {
return orb.get_primitive_tc(TCKind.tk_objref);
}
// Anything else
ObjectStreamClass osc = ObjectStreamClass.lookup(c);
if (osc == null) {
return orb.create_value_box_tc (id, "Value", orb.get_primitive_tc (TCKind.tk_value));
}
// type modifier
// REVISIT truncatable and abstract?
short modifier = (osc.isCustomMarshaled() ? org.omg.CORBA.VM_CUSTOM.value : org.omg.CORBA.VM_NONE.value);
// concrete base
TypeCode base = null;
Class superClass = c.getSuperclass();
if (superClass != null && java.io.Serializable.class.isAssignableFrom(superClass)) {
base = createTypeCodeForClassInternal(orb, superClass, vh, createdIDs);
}
// members
ValueMember[] members = translateMembers (orb, osc, vh, createdIDs);
return orb.create_value_tc(id, c.getName(), modifier, base, members);
}
public static TypeCode getPrimitiveTypeCodeForClass (ORB orb,
Class c,
ValueHandler vh) {
if (c == Integer.TYPE) {
return orb.get_primitive_tc (TCKind.tk_long);
} else if (c == Byte.TYPE) {
return orb.get_primitive_tc (TCKind.tk_octet);
} else if (c == Long.TYPE) {
return orb.get_primitive_tc (TCKind.tk_longlong);
} else if (c == Float.TYPE) {
return orb.get_primitive_tc (TCKind.tk_float);
} else if (c == Double.TYPE) {
return orb.get_primitive_tc (TCKind.tk_double);
} else if (c == Short.TYPE) {
return orb.get_primitive_tc (TCKind.tk_short);
} else if (c == Character.TYPE) {
return orb.get_primitive_tc (((ValueHandlerImpl)vh).getJavaCharTCKind());
} else if (c == Boolean.TYPE) {
return orb.get_primitive_tc (TCKind.tk_boolean);
} else {
// _REVISIT_ Not sure if this is right.
return orb.get_primitive_tc (TCKind.tk_any);
}
}
}