blob: fdf35018275c62dbff7a6c21bf827993588e73e6 [file] [log] [blame]
/*
* Copyright (c) 1998, 2012, 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 javax.rmi.CORBA.Util;
import java.util.Hashtable;
import java.io.IOException;
import com.sun.corba.se.impl.util.RepositoryId;
import com.sun.corba.se.impl.util.Utility;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.portable.IndirectionException;
import com.sun.org.omg.SendingContext.CodeBase;
import com.sun.org.omg.SendingContext.CodeBaseHelper;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.impl.logging.OMGSystemException;
import com.sun.corba.se.impl.logging.UtilSystemException;
public final class ValueHandlerImpl implements javax.rmi.CORBA.ValueHandlerMultiFormat {
// Property to override our maximum stream format version
public static final String FORMAT_VERSION_PROPERTY
= "com.sun.CORBA.MaxStreamFormatVersion";
private static final byte MAX_SUPPORTED_FORMAT_VERSION = (byte)2;
private static final byte STREAM_FORMAT_VERSION_1 = (byte)1;
// The ValueHandler's maximum stream format version to advertise,
// set in a static initializer.
private static final byte MAX_STREAM_FORMAT_VERSION;
static {
MAX_STREAM_FORMAT_VERSION = getMaxStreamFormatVersion();
}
// Looks for the FORMAT_VERSION_PROPERTY system property
// to allow the user to override our default stream format
// version. Note that this still only allows them to pick
// a supported version (1 through MAX_STREAM_FORMAT_VERSION).
private static byte getMaxStreamFormatVersion() {
try {
String propValue = (String) AccessController.doPrivileged(
new PrivilegedAction() {
public java.lang.Object run() {
return System.getProperty(ValueHandlerImpl.FORMAT_VERSION_PROPERTY);
}
});
// The property wasn't set
if (propValue == null)
return MAX_SUPPORTED_FORMAT_VERSION;
byte result = Byte.parseByte(propValue);
// REVISIT. Just set to MAX_SUPPORTED_FORMAT_VERSION
// or really let the system shutdown with this Error?
if (result < 1 || result > MAX_SUPPORTED_FORMAT_VERSION)
// XXX I18N, logging needed.
throw new ExceptionInInitializerError("Invalid stream format version: "
+ result
+ ". Valid range is 1 through "
+ MAX_SUPPORTED_FORMAT_VERSION);
return result;
} catch (Exception ex) {
// REVISIT. Swallow this or really let
// the system shutdown with this Error?
Error err = new ExceptionInInitializerError(ex);
err.initCause( ex ) ;
throw err ;
}
}
public static final short kRemoteType = 0;
public static final short kAbstractType = 1;
public static final short kValueType = 2;
private Hashtable inputStreamPairs = null;
private Hashtable outputStreamPairs = null;
private CodeBase codeBase = null;
private boolean useHashtables = true;
private boolean isInputStream = true;
private IIOPOutputStream outputStreamBridge = null;
private IIOPInputStream inputStreamBridge = null;
private OMGSystemException omgWrapper = OMGSystemException.get(
CORBALogDomains.RPC_ENCODING ) ;
private UtilSystemException utilWrapper = UtilSystemException.get(
CORBALogDomains.RPC_ENCODING ) ;
// See javax.rmi.CORBA.ValueHandlerMultiFormat
public byte getMaximumStreamFormatVersion() {
return MAX_STREAM_FORMAT_VERSION;
}
// See javax.rmi.CORBA.ValueHandlerMultiFormat
public void writeValue(org.omg.CORBA.portable.OutputStream out,
java.io.Serializable value,
byte streamFormatVersion) {
if (streamFormatVersion == 2) {
if (!(out instanceof org.omg.CORBA.portable.ValueOutputStream)) {
throw omgWrapper.notAValueoutputstream() ;
}
} else if (streamFormatVersion != 1) {
throw omgWrapper.invalidStreamFormatVersion(
new Integer(streamFormatVersion) ) ;
}
writeValueWithVersion(out, value, streamFormatVersion);
}
private ValueHandlerImpl(){}
private ValueHandlerImpl(boolean isInputStream) {
this();
useHashtables = false;
this.isInputStream = isInputStream;
}
static ValueHandlerImpl getInstance() {
return new ValueHandlerImpl();
}
static ValueHandlerImpl getInstance(boolean isInputStream) {
return new ValueHandlerImpl(isInputStream);
}
/**
* Writes the value to the stream using java semantics.
* @param out The stream to write the value to
* @param value The value to be written to the stream
**/
public void writeValue(org.omg.CORBA.portable.OutputStream _out,
java.io.Serializable value) {
writeValueWithVersion(_out, value, STREAM_FORMAT_VERSION_1);
}
private void writeValueWithVersion(org.omg.CORBA.portable.OutputStream _out,
java.io.Serializable value,
byte streamFormatVersion) {
org.omg.CORBA_2_3.portable.OutputStream out =
(org.omg.CORBA_2_3.portable.OutputStream) _out;
if (!useHashtables) {
if (outputStreamBridge == null) {
outputStreamBridge = createOutputStream();
outputStreamBridge.setOrbStream(out);
}
try {
outputStreamBridge.increaseRecursionDepth();
writeValueInternal(outputStreamBridge, out, value, streamFormatVersion);
} finally {
outputStreamBridge.decreaseRecursionDepth();
}
return;
}
IIOPOutputStream jdkToOrbOutputStreamBridge = null;
if (outputStreamPairs == null)
outputStreamPairs = new Hashtable();
jdkToOrbOutputStreamBridge = (IIOPOutputStream)outputStreamPairs.get(_out);
if (jdkToOrbOutputStreamBridge == null) {
jdkToOrbOutputStreamBridge = createOutputStream();
jdkToOrbOutputStreamBridge.setOrbStream(out);
outputStreamPairs.put(_out, jdkToOrbOutputStreamBridge);
}
try {
jdkToOrbOutputStreamBridge.increaseRecursionDepth();
writeValueInternal(jdkToOrbOutputStreamBridge, out, value, streamFormatVersion);
} finally {
if (jdkToOrbOutputStreamBridge.decreaseRecursionDepth() == 0) {
outputStreamPairs.remove(_out);
}
}
}
private void writeValueInternal(IIOPOutputStream bridge,
org.omg.CORBA_2_3.portable.OutputStream out,
java.io.Serializable value,
byte streamFormatVersion)
{
Class clazz = value.getClass();
if (clazz.isArray())
write_Array(out, value, clazz.getComponentType());
else
bridge.simpleWriteObject(value, streamFormatVersion);
}
/**
* Reads a value from the stream using java semantics.
* @param in The stream to read the value from
* @param clazz The type of the value to be read in
* @param sender The sending context runtime
**/
public java.io.Serializable readValue(org.omg.CORBA.portable.InputStream _in,
int offset,
java.lang.Class clazz,
String repositoryID,
org.omg.SendingContext.RunTime _sender)
{
// Must use narrow rather than a direct cast to a com.sun
// class. Fix for bug 4379539.
CodeBase sender = CodeBaseHelper.narrow(_sender);
org.omg.CORBA_2_3.portable.InputStream in =
(org.omg.CORBA_2_3.portable.InputStream) _in;
if (!useHashtables) {
if (inputStreamBridge == null) {
inputStreamBridge = createInputStream();
inputStreamBridge.setOrbStream(in);
inputStreamBridge.setSender(sender); //d11638
// backward compatability 4365188
inputStreamBridge.setValueHandler(this);
}
java.io.Serializable result = null;
try {
inputStreamBridge.increaseRecursionDepth();
result = (java.io.Serializable) readValueInternal(inputStreamBridge, in, offset, clazz, repositoryID, sender);
} finally {
if (inputStreamBridge.decreaseRecursionDepth() == 0) {
// Indirections are resolved immediately since
// the change to the active recursion manager,
// so this will never happen.
}
}
return result;
}
IIOPInputStream jdkToOrbInputStreamBridge = null;
if (inputStreamPairs == null)
inputStreamPairs = new Hashtable();
jdkToOrbInputStreamBridge = (IIOPInputStream)inputStreamPairs.get(_in);
if (jdkToOrbInputStreamBridge == null) {
jdkToOrbInputStreamBridge = createInputStream();
jdkToOrbInputStreamBridge.setOrbStream(in);
jdkToOrbInputStreamBridge.setSender(sender); //d11638
// backward compatability 4365188
jdkToOrbInputStreamBridge.setValueHandler(this);
inputStreamPairs.put(_in, jdkToOrbInputStreamBridge);
}
java.io.Serializable result = null;
try {
jdkToOrbInputStreamBridge.increaseRecursionDepth();
result = (java.io.Serializable) readValueInternal(jdkToOrbInputStreamBridge, in, offset, clazz, repositoryID, sender);
} finally {
if (jdkToOrbInputStreamBridge.decreaseRecursionDepth() == 0) {
inputStreamPairs.remove(_in);
}
}
return result;
}
private java.io.Serializable readValueInternal(IIOPInputStream bridge,
org.omg.CORBA_2_3.portable.InputStream in,
int offset,
java.lang.Class clazz,
String repositoryID,
com.sun.org.omg.SendingContext.CodeBase sender)
{
java.io.Serializable result = null;
if (clazz == null) {
// clazz == null indicates an FVD situation for a nonexistant class
if (isArray(repositoryID)){
read_Array(bridge, in, null, sender, offset);
} else {
bridge.simpleSkipObject(repositoryID, sender);
}
return result;
}
if (clazz.isArray()) {
result = (java.io.Serializable)read_Array(bridge, in, clazz, sender, offset);
} else {
result = (java.io.Serializable)bridge.simpleReadObject(clazz, repositoryID, sender, offset);
}
return result;
}
/**
* Returns the repository ID for the given RMI value Class.
* @param clz The class to return a repository ID for.
* @return the repository ID of the Class.
**/
public java.lang.String getRMIRepositoryID(java.lang.Class clz) {
return RepositoryId.createForJavaType(clz);
}
/**
* Indicates whether the given Class performs custom or
* default marshaling.
* @param clz The class to test for custom marshaling.
* @return True if the class performs custom marshaling, false
* if it does not.
**/
public boolean isCustomMarshaled(java.lang.Class clz) {
return ObjectStreamClass.lookup(clz).isCustomMarshaled();
}
/**
* Returns the CodeBase for this ValueHandler. This is used by
* the ORB runtime. The server sends the service context containing
* the IOR for this CodeBase on the first GIOP reply. The clients
* do the same on the first GIOP request.
* @return the SendingContext.CodeBase of this ValueHandler.
**/
public org.omg.SendingContext.RunTime getRunTimeCodeBase() {
if (codeBase != null)
return codeBase;
else {
codeBase = new FVDCodeBaseImpl();
// backward compatability 4365188
// set the valueHandler so that correct/incorrect RepositoryID
// calculations can be done based on the ORB version
FVDCodeBaseImpl fvdImpl = (FVDCodeBaseImpl) codeBase;
fvdImpl.setValueHandler(this);
return codeBase;
}
}
// methods supported for backward compatability so that the appropriate
// Rep-id calculations take place based on the ORB version
/**
* Returns a boolean of whether or not RepositoryId indicates
* FullValueDescriptor.
* used for backward compatability
*/
public boolean useFullValueDescription(Class clazz, String repositoryID)
throws IOException
{
return RepositoryId.useFullValueDescription(clazz, repositoryID);
}
public String getClassName(String id)
{
RepositoryId repID = RepositoryId.cache.getId(id);
return repID.getClassName();
}
public Class getClassFromType(String id)
throws ClassNotFoundException
{
RepositoryId repId = RepositoryId.cache.getId(id);
return repId.getClassFromType();
}
public Class getAnyClassFromType(String id)
throws ClassNotFoundException
{
RepositoryId repId = RepositoryId.cache.getId(id);
return repId.getAnyClassFromType();
}
public String createForAnyType(Class cl)
{
return RepositoryId.createForAnyType(cl);
}
public String getDefinedInId(String id)
{
RepositoryId repId = RepositoryId.cache.getId(id);
return repId.getDefinedInId();
}
public String getUnqualifiedName(String id)
{
RepositoryId repId = RepositoryId.cache.getId(id);
return repId.getUnqualifiedName();
}
public String getSerialVersionUID(String id)
{
RepositoryId repId = RepositoryId.cache.getId(id);
return repId.getSerialVersionUID();
}
public boolean isAbstractBase(Class clazz)
{
return RepositoryId.isAbstractBase(clazz);
}
public boolean isSequence(String id)
{
RepositoryId repId = RepositoryId.cache.getId(id);
return repId.isSequence();
}
/**
* If the value contains a writeReplace method then the result
* is returned. Otherwise, the value itself is returned.
* @return the true value to marshal on the wire.
**/
public java.io.Serializable writeReplace(java.io.Serializable value) {
return ObjectStreamClass.lookup(value.getClass()).writeReplace(value);
}
private void writeCharArray(org.omg.CORBA_2_3.portable.OutputStream out,
char[] array,
int offset,
int length)
{
out.write_wchar_array(array, offset, length);
}
private void write_Array(org.omg.CORBA_2_3.portable.OutputStream out, java.io.Serializable obj, Class type) {
int i, length;
if (type.isPrimitive()) {
if (type == Integer.TYPE) {
int[] array = (int[])((Object)obj);
length = array.length;
out.write_ulong(length);
out.write_long_array(array, 0, length);
} else if (type == Byte.TYPE) {
byte[] array = (byte[])((Object)obj);
length = array.length;
out.write_ulong(length);
out.write_octet_array(array, 0, length);
} else if (type == Long.TYPE) {
long[] array = (long[])((Object)obj);
length = array.length;
out.write_ulong(length);
out.write_longlong_array(array, 0, length);
} else if (type == Float.TYPE) {
float[] array = (float[])((Object)obj);
length = array.length;
out.write_ulong(length);
out.write_float_array(array, 0, length);
} else if (type == Double.TYPE) {
double[] array = (double[])((Object)obj);
length = array.length;
out.write_ulong(length);
out.write_double_array(array, 0, length);
} else if (type == Short.TYPE) {
short[] array = (short[])((Object)obj);
length = array.length;
out.write_ulong(length);
out.write_short_array(array, 0, length);
} else if (type == Character.TYPE) {
char[] array = (char[])((Object)obj);
length = array.length;
out.write_ulong(length);
writeCharArray(out, array, 0, length);
} else if (type == Boolean.TYPE) {
boolean[] array = (boolean[])((Object)obj);
length = array.length;
out.write_ulong(length);
out.write_boolean_array(array, 0, length);
} else {
// XXX I18N, logging needed.
throw new Error("Invalid primitive type : " +
obj.getClass().getName());
}
} else if (type == java.lang.Object.class) {
Object[] array = (Object[])((Object)obj);
length = array.length;
out.write_ulong(length);
for (i = 0; i < length; i++) {
Util.writeAny(out, array[i]);
}
} else {
Object[] array = (Object[])((Object)obj);
length = array.length;
out.write_ulong(length);
int callType = kValueType;
if (type.isInterface()) {
String className = type.getName();
if (java.rmi.Remote.class.isAssignableFrom(type)) {
// RMI Object reference...
callType = kRemoteType;
} else if (org.omg.CORBA.Object.class.isAssignableFrom(type)){
// IDL Object reference...
callType = kRemoteType;
} else if (RepositoryId.isAbstractBase(type)) {
// IDL Abstract Object reference...
callType = kAbstractType;
} else if (ObjectStreamClassCorbaExt.isAbstractInterface(type)) {
callType = kAbstractType;
}
}
for (i = 0; i < length; i++) {
switch (callType) {
case kRemoteType:
Util.writeRemoteObject(out, array[i]);
break;
case kAbstractType:
Util.writeAbstractObject(out,array[i]);
break;
case kValueType:
try{
out.write_value((java.io.Serializable)array[i]);
} catch(ClassCastException cce){
if (array[i] instanceof java.io.Serializable)
throw cce;
else {
Utility.throwNotSerializableForCorba(
array[i].getClass().getName());
}
}
break;
}
}
}
}
private void readCharArray(org.omg.CORBA_2_3.portable.InputStream in,
char[] array,
int offset,
int length)
{
in.read_wchar_array(array, offset, length);
}
private java.lang.Object read_Array(IIOPInputStream bridge,
org.omg.CORBA_2_3.portable.InputStream in,
Class sequence,
com.sun.org.omg.SendingContext.CodeBase sender,
int offset)
{
try {
// Read length of coming array
int length = in.read_ulong();
int i;
if (sequence == null) {
for (i = 0; i < length; i++)
in.read_value();
return null;
}
Class componentType = sequence.getComponentType();
Class actualType = componentType;
if (componentType.isPrimitive()) {
if (componentType == Integer.TYPE) {
int[] array = new int[length];
in.read_long_array(array, 0, length);
return ((java.io.Serializable)((Object)array));
} else if (componentType == Byte.TYPE) {
byte[] array = new byte[length];
in.read_octet_array(array, 0, length);
return ((java.io.Serializable)((Object)array));
} else if (componentType == Long.TYPE) {
long[] array = new long[length];
in.read_longlong_array(array, 0, length);
return ((java.io.Serializable)((Object)array));
} else if (componentType == Float.TYPE) {
float[] array = new float[length];
in.read_float_array(array, 0, length);
return ((java.io.Serializable)((Object)array));
} else if (componentType == Double.TYPE) {
double[] array = new double[length];
in.read_double_array(array, 0, length);
return ((java.io.Serializable)((Object)array));
} else if (componentType == Short.TYPE) {
short[] array = new short[length];
in.read_short_array(array, 0, length);
return ((java.io.Serializable)((Object)array));
} else if (componentType == Character.TYPE) {
char[] array = new char[length];
readCharArray(in, array, 0, length);
return ((java.io.Serializable)((Object)array));
} else if (componentType == Boolean.TYPE) {
boolean[] array = new boolean[length];
in.read_boolean_array(array, 0, length);
return ((java.io.Serializable)((Object)array));
} else {
// XXX I18N, logging needed.
throw new Error("Invalid primitive componentType : " + sequence.getName());
}
} else if (componentType == java.lang.Object.class) {
Object[] array = (Object[])java.lang.reflect.Array.newInstance(
componentType, length);
// Store this object and its beginning position
// since there might be indirections to it while
// it's been unmarshalled.
bridge.activeRecursionMgr.addObject(offset, array);
for (i = 0; i < length; i++) {
Object objectValue = null;
try {
objectValue = Util.readAny(in);
} catch(IndirectionException cdrie) {
try {
// The CDR stream had never seen the given offset
// before, so check the recursion manager (it will
// throw an IOException if it doesn't have a
// reference, either).
objectValue = bridge.activeRecursionMgr.getObject(
cdrie.offset);
} catch (IOException ie) {
// Translate to a MARSHAL exception since
// ValueHandlers aren't allowed to throw
// IOExceptions
throw utilWrapper.invalidIndirection( ie,
new Integer( cdrie.offset ) ) ;
}
}
array[i] = objectValue;
}
return ((java.io.Serializable)((Object)array));
} else {
Object[] array = (Object[])java.lang.reflect.Array.newInstance(
componentType, length);
// Store this object and its beginning position
// since there might be indirections to it while
// it's been unmarshalled.
bridge.activeRecursionMgr.addObject(offset, array);
// Decide what method call to make based on the componentType.
// If it is a componentType for which we need to load a stub,
// convert the componentType to the correct stub type.
int callType = kValueType;
boolean narrow = false;
if (componentType.isInterface()) {
boolean loadStubClass = false;
// String className = componentType.getName();
if (java.rmi.Remote.class.isAssignableFrom(componentType)) {
// RMI Object reference...
callType = kRemoteType;
// for better performance, load the stub class once
// instead of for each element of the array
loadStubClass = true;
} else if (org.omg.CORBA.Object.class.isAssignableFrom(componentType)){
// IDL Object reference...
callType = kRemoteType;
loadStubClass = true;
} else if (RepositoryId.isAbstractBase(componentType)) {
// IDL Abstract Object reference...
callType = kAbstractType;
loadStubClass = true;
} else if (ObjectStreamClassCorbaExt.isAbstractInterface(componentType)) {
// RMI Abstract Object reference...
// componentType = null;
callType = kAbstractType;
}
if (loadStubClass) {
try {
String codebase = Util.getCodebase(componentType);
String repID = RepositoryId.createForAnyType(componentType);
Class stubType =
Utility.loadStubClass(repID, codebase, componentType);
actualType = stubType;
} catch (ClassNotFoundException e) {
narrow = true;
}
} else {
narrow = true;
}
}
for (i = 0; i < length; i++) {
try {
switch (callType) {
case kRemoteType:
if (!narrow)
array[i] = (Object)in.read_Object(actualType);
else {
array[i] = Utility.readObjectAndNarrow(in, actualType);
}
break;
case kAbstractType:
if (!narrow)
array[i] = (Object)in.read_abstract_interface(actualType);
else {
array[i] = Utility.readAbstractAndNarrow(in, actualType);
}
break;
case kValueType:
array[i] = (Object)in.read_value(actualType);
break;
}
} catch(IndirectionException cdrie) {
// The CDR stream had never seen the given offset before,
// so check the recursion manager (it will throw an
// IOException if it doesn't have a reference, either).
try {
array[i] = bridge.activeRecursionMgr.getObject(
cdrie.offset);
} catch (IOException ioe) {
// Translate to a MARSHAL exception since
// ValueHandlers aren't allowed to throw
// IOExceptions
throw utilWrapper.invalidIndirection( ioe,
new Integer( cdrie.offset ) ) ;
}
}
}
return ((java.io.Serializable)((Object)array));
}
} finally {
// We've completed deserializing this object. Any
// future indirections will be handled correctly at the
// CDR level. The ActiveRecursionManager only deals with
// objects currently being deserialized.
bridge.activeRecursionMgr.removeObject(offset);
}
}
private boolean isArray(String repId){
return RepositoryId.cache.getId(repId).isSequence();
}
private String getOutputStreamClassName() {
return "com.sun.corba.se.impl.io.IIOPOutputStream";
}
private IIOPOutputStream createOutputStream() {
final String name = getOutputStreamClassName();
try {
IIOPOutputStream stream = createOutputStreamBuiltIn(name);
if (stream != null) {
return stream;
}
return createCustom(IIOPOutputStream.class, name);
} catch (Throwable t) {
// Throw exception under the carpet.
InternalError ie = new InternalError(
"Error loading " + name
);
ie.initCause(t);
throw ie;
}
}
/**
* Construct a built in implementation with priveleges.
* Returning null indicates a non-built is specified.
*/
private IIOPOutputStream createOutputStreamBuiltIn(
final String name
) throws Throwable {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<IIOPOutputStream>() {
public IIOPOutputStream run() throws IOException {
return createOutputStreamBuiltInNoPriv(name);
}
}
);
} catch (java.security.PrivilegedActionException exc) {
throw exc.getCause();
}
}
/**
* Returning null indicates a non-built is specified.
*/
private IIOPOutputStream createOutputStreamBuiltInNoPriv(
final String name
) throws IOException {
return name.equals(IIOPOutputStream.class.getName()) ?
new IIOPOutputStream() : null;
}
private String getInputStreamClassName() {
return "com.sun.corba.se.impl.io.IIOPInputStream";
}
private IIOPInputStream createInputStream() {
final String name = getInputStreamClassName();
try {
IIOPInputStream stream = createInputStreamBuiltIn(name);
if (stream != null) {
return stream;
}
return createCustom(IIOPInputStream.class, name);
} catch (Throwable t) {
// Throw exception under the carpet.
InternalError ie = new InternalError(
"Error loading " + name
);
ie.initCause(t);
throw ie;
}
}
/**
* Construct a built in implementation with priveleges.
* Returning null indicates a non-built is specified.
*/
private IIOPInputStream createInputStreamBuiltIn(
final String name
) throws Throwable {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<IIOPInputStream>() {
public IIOPInputStream run() throws IOException {
return createInputStreamBuiltInNoPriv(name);
}
}
);
} catch (java.security.PrivilegedActionException exc) {
throw exc.getCause();
}
}
/**
* Returning null indicates a non-built is specified.
*/
private IIOPInputStream createInputStreamBuiltInNoPriv(
final String name
) throws IOException {
return name.equals(IIOPInputStream.class.getName()) ?
new IIOPInputStream() : null;
}
/**
* Create a custom implementation without privileges.
*/
private <T> T createCustom(
final Class<T> type, final String className
) throws Throwable {
// Note: We use the thread context or system ClassLoader here
// since we want to load classes outside of the
// core JDK when running J2EE Pure ORB and
// talking to Kestrel.
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null)
cl = ClassLoader.getSystemClassLoader();
Class<?> clazz = cl.loadClass(className);
Class<? extends T> streamClass = clazz.asSubclass(type);
// Since the ClassLoader should cache the class, this isn't
// as expensive as it looks.
return streamClass.newInstance();
}
TCKind getJavaCharTCKind() {
return TCKind.tk_wchar;
}
}