| /* |
| * 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; |
| } |
| } |