blob: 8fe5335e0c11de5778cab664fa2fcdc021c169fa [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 java.io.Externalizable;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.rmi.AccessException;
import java.rmi.MarshalException;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.ServerError;
import java.rmi.ServerException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Stub;
import javax.rmi.CORBA.Tie;
import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.UtilDelegate;
import javax.rmi.CORBA.ValueHandler;
import org.apache.yoko.rmi.util.GetSystemPropertyAction;
import org.apache.yoko.osgi.ProviderLocator;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.INVALID_TRANSACTION;
import org.omg.CORBA.INV_OBJREF;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.NO_PERMISSION;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.TRANSACTION_REQUIRED;
import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.portable.IDLEntity;
import org.omg.CORBA.portable.UnknownException;
public class UtilImpl implements UtilDelegate {
private static final Logger logger = Logger.getLogger(UtilImpl.class.getName());
// Note: this field must be declared before the static intializer that calls Util.loadClass
// since that method will call loadClass0 which uses this field... if it is below the static
// initializer the _secman field will be null
private static final SecMan _secman = getSecMan();
private static final ClassLoader BEST_GUESS_AT_EXTENSION_CLASS_LOADER;
static {
ClassLoader candidateLoader = getClassLoader(UtilImpl.class);
if (candidateLoader == null) {
// looks like this class was loaded by the boot class loader
// so it is safe to try loading stuff by reflection without
// worrying about whether we have imported the packages into the OSGi bundle
candidateLoader = findFirstNonNullLoader(
"sun.net.spi.nameservice.dns.DNSNameService",
"javax.transaction.UserTransaction");
}
// We will try to find the extension class
// loader by ascending the loader hierarchy
// starting from whatever loader we found.
for (ClassLoader l = candidateLoader; l != null; l = l.getParent()) {
candidateLoader = l;
}
BEST_GUESS_AT_EXTENSION_CLASS_LOADER = candidateLoader;
}
private static ClassLoader findFirstNonNullLoader(String...classNames) {
for (String className : classNames) {
try {
final Class<?> c = Class.forName(className);
ClassLoader cl = getClassLoader(c);
if (cl != null) return cl;
} catch (Exception|NoClassDefFoundError swallowed) {
}
}
return null;
}
/**
* Translate a CORBA SystemException to the corresponding RemoteException
*/
public RemoteException mapSystemException(final SystemException theException) {
SystemException ex = theException;
if (ex instanceof UnknownException) {
Throwable orig = ((UnknownException) ex).originalEx;
if (orig instanceof Error) {
return new ServerError("Error occurred in server thread",
(Error) orig);
} else if (orig instanceof RemoteException) {
return new ServerException(
"RemoteException occurred in server thread",
(Exception) orig);
} else if (orig instanceof RuntimeException) {
throw (RuntimeException) orig;
}
}
Class<? extends SystemException> exclass = ex.getClass();
String name = exclass.getName();
// construct the exception message according to �1.4.8
StringBuffer buf = new StringBuffer("CORBA ");
final String prefix = "org.omg.CORBA";
if (name.startsWith(prefix)) {
buf.append(name.substring(prefix.length() + 1));
} else {
buf.append(name);
}
buf.append(" ");
buf.append(ex.minor);
switch (ex.completed.value()) {
case org.omg.CORBA.CompletionStatus._COMPLETED_YES:
buf.append(" Yes");
break;
case org.omg.CORBA.CompletionStatus._COMPLETED_NO:
buf.append(" No");
break;
case org.omg.CORBA.CompletionStatus._COMPLETED_MAYBE:
buf.append(" Maybe");
break;
}
String exceptionMessage = buf.toString();
return createRemoteException(ex, exceptionMessage);
}
private RemoteException createRemoteException(SystemException sysEx, String s) {
RemoteException result;
try {
throw sysEx;
} catch (BAD_PARAM|COMM_FAILURE|MARSHAL e) {
result = new MarshalException(s);
} catch (INV_OBJREF|NO_IMPLEMENT|OBJECT_NOT_EXIST e) {
result = new NoSuchObjectException(s);
} catch(NO_PERMISSION e) {
result = new AccessException(s);
} catch (TRANSACTION_REQUIRED e) {
result = createRemoteException("javax.transaction.TransactionRequiredException", s);
} catch (TRANSACTION_ROLLEDBACK e) {
result = createRemoteException("javax.transaction.TransactionRolledbackException", s);
} catch (INVALID_TRANSACTION e) {
result = createRemoteException("javax.transaction.InvalidTransactionException", s);
} catch (SystemException catchAll) {
result = new RemoteException(s);
}
result.detail = sysEx;
return result;
}
private static RemoteException createRemoteException(String className, String s) {
RemoteException result;
try {
@SuppressWarnings("unchecked")
Class<? extends RemoteException> clazz = Util.loadClass(className, null, null);
Constructor<? extends RemoteException> ctor = clazz.getConstructor(String.class);
result = ctor.newInstance(s);
} catch (Throwable t) {
result = new RemoteException(s);
result.addSuppressed(t);
}
return result;
}
static SystemException mapRemoteException(RemoteException rex) {
if (rex.detail instanceof org.omg.CORBA.SystemException)
return (org.omg.CORBA.SystemException) rex.detail;
if (rex.detail instanceof RemoteException)
rex = (RemoteException) rex.detail;
SystemException sysEx;
if (rex instanceof java.rmi.NoSuchObjectException) {
sysEx = new org.omg.CORBA.INV_OBJREF(rex.getMessage());
} else if (rex instanceof java.rmi.AccessException) {
sysEx = new org.omg.CORBA.NO_PERMISSION(rex.getMessage());
} else if (rex instanceof java.rmi.MarshalException) {
sysEx = new org.omg.CORBA.MARSHAL(rex.getMessage());
} else {
sysEx = createSystemException(rex);
}
sysEx.initCause(rex);
throw sysEx;
}
private static SystemException createSystemException(RemoteException rex) {
return createSystemException(rex, rex.getClass());
}
/**
* utility method to check for JTA exception types without linking to the JTA classes directly
*/
private static SystemException createSystemException(RemoteException rex, Class<?> fromClass) {
// Recurse up the parent chain,
// until we reach a known JTA type.
switch(fromClass.getName()) {
// Of course, we place some known elephants in Cairo.
case "java.lang.Object":
case "java.lang.Throwable":
case "java.lang.Exception":
case "java.lang.RuntimeException":
case "java.lang.Error":
case "java.io.IOException":
case "java.rmi.RemoteException":
return new UnknownException(rex);
case "javax.transaction.InvalidTransactionException":
return new INVALID_TRANSACTION(rex.getMessage());
case "javax.transaction.TransactionRolledbackException":
return new TRANSACTION_ROLLEDBACK(rex.getMessage());
case "javax.transaction.TransactionRequiredException":
return new TRANSACTION_REQUIRED(rex.getMessage());
}
return createSystemException(rex, fromClass.getSuperclass());
}
/**
* Write an org.omg.CORBA.Any containing the given object.
* <p/>
* The object is not converted or translated, simply written. Thus, it must
* be either an IDL-generated entity, a Serializable value or an
* org.omg.CORBA.Object. Specifically, a Remote objects and Servants cannot
* be written, but their corresponding Stubs can.
*
* @param out The stream to which the value should be written
* @param obj The object/value to write
* @throws org.omg.CORBA.MARSHAL if the value cannot be written
*/
public void writeAny(org.omg.CORBA.portable.OutputStream out, Object obj)
throws org.omg.CORBA.SystemException {
//
// In this implementation of RMI/IIOP we do not use type codes
// beyond the implementation of this method, and it's
// counterpart readAny.
//
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
Any any = orb.create_any();
if (obj == null) {
// JDK 1.3.1-1 doesn't like NULL typecodes, so
// we write it as a null Value.
any.insert_Value(null);
} else if (obj instanceof String) {
any.insert_Value((String) obj);
} else if (obj instanceof org.omg.CORBA.Object) {
any.insert_Object((org.omg.CORBA.Object) obj);
} else if (obj instanceof Any) {
any.insert_any((Any) obj);
} else if (obj instanceof IDLEntity) {
any.insert_Value((Serializable) obj);
} else if (obj instanceof java.rmi.Remote) {
Remote ro = (Remote) obj;
org.omg.CORBA.Object corba_obj;
try {
corba_obj = (org.omg.CORBA.Object) PortableRemoteObject
.toStub(ro);
} catch (java.rmi.NoSuchObjectException ex) {
throw (org.omg.CORBA.MARSHAL) new org.omg.CORBA.MARSHAL(
"object not exported " + ro).initCause(ex);
}
any.insert_Object((org.omg.CORBA.Object) corba_obj);
} else if (obj instanceof Serializable || obj instanceof Externalizable) {
any.insert_Value((Serializable) obj);
} else {
throw new MARSHAL("cannot write as " + obj.getClass()
+ " to an Any");
}
out.write_any(any);
}
public Object readAny(org.omg.CORBA.portable.InputStream in)
throws org.omg.CORBA.SystemException {
Any any = in.read_any();
TypeCode typecode = any.type();
switch (typecode.kind().value()) {
case TCKind._tk_null:
case TCKind._tk_void:
return null;
case TCKind._tk_value:
case TCKind._tk_value_box:
return any.extract_Value();
case TCKind._tk_abstract_interface:
org.omg.CORBA_2_3.portable.InputStream in23 = (org.omg.CORBA_2_3.portable.InputStream) any
.create_input_stream();
return in23.read_abstract_interface();
case TCKind._tk_string:
return any.extract_string();
case TCKind._tk_objref:
org.omg.CORBA.Object ref = any.extract_Object();
return ref;
case TCKind._tk_any:
return any.extract_any();
default:
String id = "<unknown>";
try {
id = typecode.id();
} catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
}
throw new MARSHAL("cannot extract " + id + " ("
+ typecode.kind().value() + ") value from Any");
}
}
/**
* Write a remote object. It must already be exported.
* <p/>
* This method accepts values of org.omg.CORBA.Object (including stubs), and
* instances of java.rmi.Remote for objects that have already been exported.
*/
public void writeRemoteObject(org.omg.CORBA.portable.OutputStream out,
Object obj) throws org.omg.CORBA.SystemException {
org.omg.CORBA.Object objref = null;
if (obj == null) {
out.write_Object(null);
return;
} else if (obj instanceof org.omg.CORBA.Object) {
objref = (org.omg.CORBA.Object) obj;
} else if (obj instanceof Remote) {
try {
objref = (javax.rmi.CORBA.Stub) PortableRemoteObject
.toStub((java.rmi.Remote) obj);
} catch (java.rmi.NoSuchObjectException ex) {
}
if (objref == null) {
try {
PortableRemoteObject.exportObject((java.rmi.Remote) obj);
objref = (javax.rmi.CORBA.Stub) PortableRemoteObject
.toStub((java.rmi.Remote) obj);
} catch (java.rmi.RemoteException ex) {
throw (MARSHAL) new MARSHAL("cannot convert Remote to Object").initCause(ex);
}
}
} else {
throw new MARSHAL(
"object is neither Remote nor org.omg.CORBA.Object: "
+ obj.getClass().getName());
}
out.write_Object(objref);
}
public void writeAbstractObject(org.omg.CORBA.portable.OutputStream out, Object obj) {
logger.finer("writeAbstractObject.1 " + " out=" + out);
if (obj instanceof org.omg.CORBA.Object || obj instanceof Serializable) {
// skip //
} else if (obj instanceof Remote) {
org.omg.CORBA.Object objref = null;
try {
objref = (org.omg.CORBA.Object) PortableRemoteObject
.toStub((Remote) obj);
} catch (java.rmi.NoSuchObjectException ex) {
}
if (objref == null) {
try {
PortableRemoteObject.exportObject((Remote) obj);
objref = (org.omg.CORBA.Object) PortableRemoteObject
.toStub((Remote) obj);
} catch (RemoteException ex) {
throw (MARSHAL) new MARSHAL("unable to export object").initCause(ex);
}
}
obj = objref;
}
org.omg.CORBA_2_3.portable.OutputStream out_ = (org.omg.CORBA_2_3.portable.OutputStream) out;
logger.finer("writeAbstractObject.2 " + " out=" + out);
out_.write_abstract_interface(obj);
}
@SuppressWarnings("unchecked")
protected java.util.Map<Remote, Tie> tie_map() {
return RMIState.current().tie_map;
}
public void registerTarget(Tie tie, Remote obj) {
if (obj == null)
throw new IllegalArgumentException("remote object is null");
tie.setTarget(obj);
tie_map().put(obj, tie);
// log.info("exported instance of "+obj.getClass()+" in
// "+RMIState.current().getName());
}
public Tie getTie(Remote obj) {
if (obj == null)
return null;
return tie_map().get(obj);
}
public ValueHandler createValueHandler() {
return RMIState.current().createValueHandler();
// return new ValueHandlerImpl (null);
}
public String getCodebase(@SuppressWarnings("rawtypes") Class clz) {
if (clz == null)
return null;
if (clz.isArray())
return getCodebase(clz.getComponentType());
if (clz.isPrimitive())
return null;
ClassLoader theLoader = clz.getClassLoader();
// ignore system classes
if (theLoader == null)
return null;
// ignore J2SE base class loader
if (theLoader == (Object.class).getClassLoader())
return null;
// ignore standard extensions
if (theLoader == BEST_GUESS_AT_EXTENSION_CLASS_LOADER)
return null;
RMIState state = RMIState.current();
ClassLoader stateLoader = state.getClassLoader();
try {
// is the class loaded with the stateLoader?
if (clz.equals(stateLoader.loadClass(clz.getName()))) {
java.net.URL codebaseURL = state.getCodeBase();
if (codebaseURL != null) {
logger.finer("class " + clz.getName() + " => "
+ codebaseURL);
// System.out.println ("class "+clz.getName()+" =>
// "+codebaseURL);
return codebaseURL.toString();
}
}
} catch (ClassNotFoundException ex) {
// ignore
}
return AccessController.doPrivileged(new GetSystemPropertyAction("java.rmi.server.codebase"));
}
static class SecMan extends java.rmi.RMISecurityManager {
@SuppressWarnings("rawtypes")
public Class[] getClassContext() {
return super.getClassContext();
}
}
private static SecMan getSecMan() {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<SecMan>() {
public SecMan run() {
return new SecMan();
}
});
} catch (PrivilegedActionException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("rawtypes")
public Class loadClass(String name, String codebase, ClassLoader loader)
throws ClassNotFoundException {
try {
return loadClass0(name, codebase, loader);
} catch (ClassNotFoundException ex) {
logger.log(Level.FINER, "cannot load from " + codebase + " " +
ex.getMessage(), ex);
throw ex;
}
}
static public Class<?> loadClass0(String name, String codebase, ClassLoader loader)
throws ClassNotFoundException {
try {
return ProviderLocator.loadClass(name, null, loader);
} catch (ClassNotFoundException e) {
//skip
}
Class<?> result = null;
ClassLoader stackLoader = null;
ClassLoader thisLoader = Util.class.getClassLoader();
Class<?>[] stack = _secman.getClassContext();
for (int i = 1; i < stack.length; i++) {
ClassLoader testLoader = stack[i].getClassLoader();
if (testLoader != null && testLoader != thisLoader) {
stackLoader = thisLoader;
break;
}
}
if (stackLoader != null) {
try {
result = stackLoader.loadClass(name);
} catch (ClassNotFoundException ex) {
// skip //
}
if (result != null) {
return result;
}
}
// try loading using our loader, just in case we really were loaded
// using the same classloader the delegate is in.
if (thisLoader != null) {
try {
result = thisLoader.loadClass(name);
} catch (ClassNotFoundException ex) {
// skip //
}
if (result != null) {
return result;
}
}
if (codebase != null && !"".equals(codebase)
&& !Boolean.getBoolean("java.rmi.server.useCodeBaseOnly")) {
logger.finer("trying RMIClassLoader");
try (URLClassLoader url_loader = new URLClassLoader(new URL[]{new URL(codebase)}, loader)) {
result = url_loader.loadClass(name);
} catch (ClassNotFoundException ex) {
logger.log(Level.FINER, "RMIClassLoader says " + ex.getMessage(), ex);
} catch (MalformedURLException ex) {
logger.log(Level.FINER, "RMIClassLoader says " + ex.getMessage(), ex);
logger.finer("FAILED class download " + name + " from " + codebase + " " + ex.getMessage());
} catch (RuntimeException ex) {
logger.log(Level.FINER, "FAILED class download " + name + " from " + codebase + " " + ex.getMessage(), ex);
} catch (IOException unimportant) {
}
if (result != null) {
return result;
}
} else {
codebase = (String) AccessController.doPrivileged(new GetSystemPropertyAction("java.rmi.server.codebase"));
if (codebase != null) {
try {
result = java.rmi.server.RMIClassLoader.loadClass(codebase,
name);
} catch (ClassNotFoundException ex) {
// skip //
} catch (MalformedURLException ex) {
// skip //
}
if (result != null) {
return result;
}
}
}
if (loader == null) {
loader = getContextClassLoader();
}
try {
result = loader.loadClass(name);
} catch (ClassNotFoundException ex) {
logger.log(Level.FINER, "LocalLoader says " + ex.getMessage(), ex);
}
if (result != null) {
return result;
}
throw new ClassNotFoundException(name);
}
public boolean isLocal(Stub stub) throws RemoteException {
try {
if (stub instanceof RMIStub) {
return true;
} else {
return stub._is_local();
}
} catch (org.omg.CORBA.SystemException ex) {
throw mapSystemException(ex);
}
}
public RemoteException wrapException(Throwable ex) {
if (ex instanceof Error) {
return new java.rmi.ServerError(ex.getMessage(), (Error) ex);
} else if (ex instanceof RemoteException) {
return new java.rmi.ServerException(ex.getMessage(), (Exception) ex);
} else if (ex instanceof org.omg.CORBA.portable.UnknownException) {
org.omg.CORBA.portable.UnknownException uex = (org.omg.CORBA.portable.UnknownException) ex;
return new java.rmi.ServerError(
ex.getMessage(),
(uex.originalEx instanceof Error ? (Error) uex.originalEx
: new Error("[OTHER EXCEPTION] " + ex.getMessage())));
} else if (ex instanceof org.omg.CORBA.SystemException) {
return mapSystemException((org.omg.CORBA.SystemException) ex);
} else if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
} else {
return new java.rmi.RemoteException(ex.getMessage(), ex);
}
}
static ClassLoader getContextClassLoader() {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
}
static ClassLoader getClassLoader(final Class<?> clz) {
if (System.getSecurityManager() == null) {
return clz.getClassLoader();
} else {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return clz.getClassLoader();
}
});
}
}
static Object copyRMIStub(RMIStub stub) throws RemoteException {
ClassLoader loader = getContextClassLoader();
if (getClassLoader(stub._descriptor.type) == loader) {
return stub;
}
RemoteDescriptor desc = stub._descriptor;
Class<?> targetClass;
try {
targetClass = Util.loadClass(desc.type.getName(), stub
._get_codebase(), loader);
} catch (ClassNotFoundException ex) {
logger.log(Level.FINER, "copyRMIStub exception (current loader is: " + loader
+ ") " + ex.getMessage(), ex);
throw new RemoteException("Class not found", ex);
}
return PortableRemoteObjectImpl.narrow1(RMIState.current(), stub,
targetClass);
}
static boolean copy_with_corba = false;
/**
* Copy a single object, maintaining internal reference integrity.
* <p/>
* This is done by writing and reading the object to/from a temporary
* stream. As such, this should be called after the receiving context's
* class-loaders etc. have been set up.
*/
public Object copyObject(Object obj, org.omg.CORBA.ORB orb)
throws RemoteException {
if (obj == null)
return null;
if (orb == null)
throw new NullPointerException();
if (obj instanceof String || obj instanceof Number)
return obj;
if (obj instanceof RMIStub) {
return copyRMIStub((RMIStub) obj);
}
/*
* try { org.omg.CORBA_2_3.portable.OutputStream out =
* (org.omg.CORBA_2_3.portable.OutputStream) orb.create_output_stream
* ();
*
* out.write_value ((java.io.Serializable) obj);
*
* org.omg.CORBA_2_3.portable.InputStream in =
* (org.omg.CORBA_2_3.portable.InputStream) out.create_input_stream ();
*
* return in.read_value ();
* } catch (org.omg.CORBA.SystemException ex) { throw
* mapSystemException (ex); }
*/
try {
TypeRepository rep = RMIState.current().getTypeRepository();
CopyState state = new CopyState(rep);
return state.copy(obj);
} catch (CopyRecursionException ex) {
throw new MarshalException("unable to resolve recursion", ex);
} catch (org.omg.CORBA.SystemException ex) {
throw mapSystemException(ex);
}
}
static final Object READ_SERIALIZABLE_KEY = new Object();
/**
* Copy an array of objects, maintaining internal reference integrity.
* <p/>
* This is done by writing and reading the object array to/from a temporary
* stream. As such, this should be called after the receiving context's
* class-loaders etc. have been set up.
*/
public Object[] copyObjects(Object[] objs, org.omg.CORBA.ORB orb)
throws RemoteException {
if (objs == null || orb == null)
throw new NullPointerException();
if (objs.length == 0)
return objs;
try {
TypeRepository rep = RMIState.current().getTypeRepository();
CopyState state = new CopyState(rep);
try {
return (Object[]) state.copy(objs);
} catch (CopyRecursionException ex) {
throw new MarshalException("unable to resolve recursion", ex);
}
/*
* int length = objs.length;
*
* for (int i = 0; i < length; i++) {
*
* Object val = objs[i];
*
* if (val == null || val instanceof String || val instanceof
* Number) { // do nothing, just leave the object in place //
* } else if (val instanceof RMIStub) { objs[i] =
* copyRMIStub((RMIStub)val);
* } else { if (orb == null) { orb = RMIState.current().getORB(); }
*
* if (out == null) { out =
* (org.omg.CORBA_2_3.portable.OutputStream) orb
* .create_output_stream(); }
*
* out.write_value((java.io.Serializable) val); objs[i] =
* READ_SERIALIZABLE_KEY; }
* }
*
* if (out != null) {
*
* org.omg.CORBA_2_3.portable.InputStream in =
* (org.omg.CORBA_2_3.portable.InputStream) out
* .create_input_stream();
*
* for (int i = 0; i < length; i++) { if (objs[i] ==
* READ_SERIALIZABLE_KEY) { objs[i] = in.read_value(); } } }
*
* return objs;
*/
} catch (org.omg.CORBA.SystemException ex) {
throw mapSystemException(ex);
}
}
public void unexportObject(Remote obj)
throws java.rmi.NoSuchObjectException {
if (obj == null)
return;
java.util.Map<Remote, Tie> tie_map = tie_map();
if (tie_map == null)
return;
Tie tie = tie_map.remove(obj);
if (tie == null) {
logger.fine("unexporting unknown instance of "
+ obj.getClass().getName() + " from "
+ RMIState.current().getName());
return;
} else {
logger.finer("unexporting instance of " + obj.getClass().getName()
+ " from " + RMIState.current().getName());
}
tie.deactivate();
}
}