blob: 859186d41bce556718b311939e051ac2004fa96a [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed 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 com.intellij.execution.rmi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.util.containers.ContainerUtilRt;
import java.lang.ref.WeakReference;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class RemoteObject implements Remote, Unreferenced {
private final WeakReference<RemoteObject> myWeakRef;
private RemoteObject myParent;
private final Map<RemoteObject, Remote> myChildren = new ConcurrentHashMap<RemoteObject, Remote>();
public RemoteObject() {
myWeakRef = new WeakReference<RemoteObject>(this);
}
public WeakReference<RemoteObject> getWeakRef() {
return myWeakRef;
}
@Nullable
public synchronized <T extends Remote> T export(@Nullable T child) throws RemoteException {
if (child == null) return null;
@SuppressWarnings("unchecked") final T result = (T)UnicastRemoteObject.exportObject(child, 0);
myChildren.put((RemoteObject)child, result);
((RemoteObject)child).myParent = this;
return result;
}
@Nullable
public <T extends Remote> T export2(@Nullable T child) throws RemoteException {
return export(child);
}
public synchronized void unexportChildren() throws RemoteException {
final ArrayList<RemoteObject> childrenRefs = new ArrayList<RemoteObject>(myChildren.keySet());
myChildren.clear();
for (RemoteObject child : childrenRefs) {
child.unreferenced();
}
}
public synchronized void unexportChildren(@NotNull Collection<WeakReference<RemoteObject>> children) throws RemoteException {
if (children.isEmpty()) return;
final ArrayList<RemoteObject> list = new ArrayList<RemoteObject>(children.size());
for (WeakReference<? extends RemoteObject> child : children) {
ContainerUtilRt.addIfNotNull(child.get(), list);
}
myChildren.keySet().removeAll(list);
for (RemoteObject child : list) {
child.unreferenced();
}
}
public synchronized void unreferenced() {
if (myParent != null) {
myParent.myChildren.remove(this);
myParent = null;
try {
unexportChildren();
UnicastRemoteObject.unexportObject(this, false);
}
catch (RemoteException e) {
//noinspection CallToPrintStackTrace
e.printStackTrace();
}
}
}
public Throwable wrapException(Throwable ex) {
boolean foreignException = false;
Throwable each = ex;
while (each != null) {
if (!each.getClass().getName().startsWith("java.") && !isKnownException(each)) {
foreignException = true;
break;
}
each = each.getCause();
}
if (foreignException) {
final RuntimeException wrapper = new RuntimeException(ex.toString());
wrapper.setStackTrace(ex.getStackTrace());
wrapper.initCause(wrapException(ex.getCause()));
ex = wrapper;
}
return ex;
}
protected boolean isKnownException(Throwable ex) {
return false;
}
}