2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.util;
18 import com.intellij.openapi.Disposable;
19 import com.intellij.openapi.util.objectTree.ObjectTree;
20 import com.intellij.openapi.util.objectTree.ObjectTreeAction;
21 import com.intellij.util.ReflectionUtil;
22 import com.intellij.util.containers.ContainerUtil;
23 import org.jetbrains.annotations.NonNls;
24 import org.jetbrains.annotations.NotNull;
25 import org.jetbrains.annotations.Nullable;
26 import org.jetbrains.annotations.TestOnly;
28 import java.lang.reflect.Field;
29 import java.lang.reflect.Modifier;
32 public class Disposer {
33 private static final ObjectTree<Disposable> ourTree;
37 ourTree = new ObjectTree<Disposable>();
39 catch (NoClassDefFoundError e) {
40 throw new RuntimeException("loader=" + Disposer.class.getClassLoader(), e);
44 private static final ObjectTreeAction<Disposable> ourDisposeAction = new ObjectTreeAction<Disposable>() {
46 public void execute(@NotNull final Disposable each) {
47 //noinspection SSBasedInspection
52 public void beforeTreeExecution(@NotNull final Disposable parent) {
53 if (parent instanceof Disposable.Parent) {
54 ((Disposable.Parent)parent).beforeTreeDispose();
59 private static boolean ourDebugMode;
65 public static Disposable newDisposable() {
66 return new Disposable() {
68 public void dispose() {
73 private static final Map<String, Disposable> ourKeyDisposables = ContainerUtil.createConcurrentWeakMap();
75 public static void register(@NotNull Disposable parent, @NotNull Disposable child) {
76 register(parent, child, null);
79 public static void register(@NotNull Disposable parent, @NotNull Disposable child, @NonNls @Nullable final String key) {
80 assert parent != child : " Cannot register to itself";
82 ourTree.register(parent, child);
85 assert get(key) == null;
86 ourKeyDisposables.put(key, child);
87 register(child, new Disposable() {
89 public void dispose() {
90 ourKeyDisposables.remove(key);
96 public static boolean isDisposed(@NotNull Disposable disposable) {
97 return !ourTree.containsKey(disposable);
100 public static Disposable get(@NotNull String key) {
101 return ourKeyDisposables.get(key);
104 public static void dispose(@NotNull Disposable disposable) {
105 dispose(disposable, true);
108 public static void dispose(@NotNull Disposable disposable, boolean processUnregistered) {
109 ourTree.executeAll(disposable, true, ourDisposeAction, processUnregistered);
112 public static void disposeChildAndReplace(@NotNull Disposable toDispose, @NotNull Disposable toReplace) {
113 ourTree.executeChildAndReplace(toDispose, toReplace, true, ourDisposeAction);
117 public static ObjectTree<Disposable> getTree() {
121 public static void assertIsEmpty() {
122 assertIsEmpty(false);
124 public static void assertIsEmpty(boolean throwError) {
126 ourTree.assertIsEmpty(throwError);
131 public static boolean isEmpty() {
132 return ourDebugMode && ourTree.isEmpty();
138 public static boolean setDebugMode(final boolean debugMode) {
139 boolean oldValue = ourDebugMode;
140 ourDebugMode = debugMode;
144 public static boolean isDebugMode() {
148 public static void clearOwnFields(@NotNull Object object) {
149 final Field[] all = object.getClass().getDeclaredFields();
150 for (Field each : all) {
151 if ((each.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) continue;
152 ReflectionUtil.resetField(object, each);
157 * @return object registered on parentDisposable which is equal to object, or null if not found
160 public static <T extends Disposable> T findRegisteredObject(@NotNull Disposable parentDisposable, @NotNull T object) {
161 return ourTree.findRegisteredObject(parentDisposable, object);