blob: c7949fec629a5c03f20121df6f9b5f2839bcc805 [file] [log] [blame]
/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.yoko.rmi.impl;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.CORBA.portable.OutputStream;
import javax.rmi.CORBA.Util;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map;
class IDLEntityDescriptor extends ValueDescriptor {
private final boolean isCorba;
private final Class helperType;
IDLEntityDescriptor(Class type, TypeRepository repository) {
super(type, repository);
isCorba = org.omg.CORBA.Object.class.isAssignableFrom(type);
try {
final String helperName = type.getName() + "Helper";
helperType = Util.loadClass(helperName, null, type.getClassLoader());
} catch (ClassNotFoundException ex) {
throw new RuntimeException("cannot load IDL Helper class for "
+ type, ex);
}
}
@Override
protected final String genIDLName() {
return "org_omg_boxedIDL_" + super.genIDLName();
}
private volatile Method readMethod = null;
private Method getReadMethod() {
if (null == readMethod) readMethod = genHelperMethod("write");
return readMethod;
}
private volatile Method writeMethod = null;
private Method getWriteMethod() {
if (null == writeMethod) writeMethod = genHelperMethod("write");
return writeMethod;
}
private volatile Method typeMethod = null;
private Method getTypeMethod() {
if (null == typeMethod) typeMethod = genHelperMethod("type");
return typeMethod;
}
private Method genHelperMethod(final String name) {
return AccessController.doPrivileged(new PrivilegedAction<Method>() {
@Override
public Method run() {
for (Method m: helperType.getDeclaredMethods()) {
if (m.getName().equals(name)) return m;
}
throw new RuntimeException("Unable to find " + name + " method for " + helperType.getName());
}
});
}
/** Read an instance of this value from a CDR stream */
@Override
public Object read(InputStream in) {
org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
// there are two ways we need to deal with IDLEntity classes. Ones that also implement
// the CORBA Object interface are actual corba objects, and must be handled that way.
// Other IDLEntity classes are just transmitted by value.
if (isCorba) {
return _in.read_Object(type);
} else {
// we directly call read_value() on the stream here, with the explicitly specified
// repository ID. The input stream will handle validating the value tag for us, and eventually
// will call our readValue() method to deserialize the object.
return _in.read_value(getRepositoryID());
}
}
@Override
public Serializable readValue(final InputStream in, final Map offsetMap, final Integer offset) {
try {
Serializable value = (Serializable) getReadMethod().invoke(null, new Object[]{in});
offsetMap.put(offset, value);
return value;
} catch (InvocationTargetException ex) {
throw (MARSHAL)new MARSHAL(""+ex.getCause()).initCause(ex.getCause());
} catch (IllegalAccessException ex) {
throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
}
}
/** Write an instance of this value to a CDR stream */
@Override
public void write(OutputStream out, Object val) {
org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;
// there are two ways we need to deal with IDLEntity classes. Ones that also implement
// the CORBA Object interface are actual corba objects, and must be handled that way.
// Other IDLEntity classes are just transmitted by value.
if (val instanceof ObjectImpl) {
_out.write_Object((org.omg.CORBA.Object)val);
} else {
// we directly call write_value() on the stream here, with the explicitly specified
// repository ID. the output stream will handle writing the value tag for us, and eventually
// will call our writeValue() method to serialize the object.
_out.write_value((Serializable)val, getRepositoryID());
}
}
@Override
public void writeValue(OutputStream out, Serializable val) {
try {
getWriteMethod().invoke(null, new Object[] { out, val });
} catch (InvocationTargetException ex) {
throw (MARSHAL)new MARSHAL(""+ ex.getCause()).initCause(ex.getCause());
} catch (IllegalAccessException ex) {
throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
}
}
@Override
protected TypeCode genTypeCode() {
try {
return (TypeCode) getTypeMethod().invoke(null, new Object[0]);
} catch (InvocationTargetException ex) {
throw (MARSHAL)new MARSHAL(""+ex.getCause()).initCause(ex.getCause());
} catch (IllegalAccessException ex) {
throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
}
}
}