private boolean disposeSelf() {
    myDisposeInProgress = true;
    final CommandProcessor commandProcessor = CommandProcessor.getInstance();
    final Ref<Boolean> canClose = new Ref<Boolean>(Boolean.TRUE);
    for (final Project project : ProjectManagerEx.getInstanceEx().getOpenProjects()) {
      try {
        commandProcessor.executeCommand(
            project,
            new Runnable() {
              public void run() {
                canClose.set(ProjectUtil.closeAndDispose(project));
              }
            },
            ApplicationBundle.message("command.exit"),
            null);
      } catch (Throwable e) {
        LOG.error(e);
      }
      if (!canClose.get()) {
        myDisposeInProgress = false;
        return false;
      }
    }
    Disposer.dispose(this);

    Disposer.assertIsEmpty();
    return true;
  }
 @Override
 public UpdateInfoTree showUpdateProjectInfo(
     UpdatedFiles updatedFiles,
     String displayActionName,
     ActionInfo actionInfo,
     boolean canceled) {
   if (!myProject.isOpen() || myProject.isDisposed()) return null;
   ContentManager contentManager = getContentManager();
   if (contentManager == null) {
     return null; // content manager is made null during dispose; flag is set later
   }
   final UpdateInfoTree updateInfoTree =
       new UpdateInfoTree(contentManager, myProject, updatedFiles, displayActionName, actionInfo);
   Content content =
       ContentFactory.SERVICE
           .getInstance()
           .createContent(
               updateInfoTree,
               canceled
                   ? VcsBundle.message(
                       "toolwindow.title.update.action.canceled.info", displayActionName)
                   : VcsBundle.message("toolwindow.title.update.action.info", displayActionName),
               true);
   Disposer.register(content, updateInfoTree);
   ContentsUtil.addContent(contentManager, content, true);
   ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.VCS).activate(null);
   updateInfoTree.expandRootChildren();
   return updateInfoTree;
 }
  public EditorsSplitters(
      final FileEditorManagerImpl manager,
      DockManager dockManager,
      boolean createOwnDockableContainer) {
    super(new BorderLayout());
    setOpaque(false);
    myManager = manager;
    myFocusWatcher = new MyFocusWatcher();
    setFocusTraversalPolicy(new MyFocusTraversalPolicy());
    setTransferHandler(new MyTransferHandler());
    clear();

    if (createOwnDockableContainer) {
      DockableEditorTabbedContainer dockable =
          new DockableEditorTabbedContainer(myManager.getProject(), this, false);
      Disposer.register(manager.getProject(), dockable);
      dockManager.register(dockable);
    }

    UISettings.getInstance()
        .addUISettingsListener(
            new UISettingsListener() {
              @Override
              public void uiSettingsChanged(UISettings source) {
                updateBackground();
              }
            },
            manager.getProject());
    updateBackground();
  }
  @Override
  protected void tearDown() throws Exception {
    try {
      Disposer.dispose(myTestRootDisposable);
      cleanupSwingDataStructures();
      cleanupDeleteOnExitHookList();
    } finally {
      if (shouldContainTempFiles()) {
        FileUtil.resetCanonicalTempPathCache(ORIGINAL_TEMP_DIR);
        if (ourPathToKeep != null && FileUtil.isAncestor(myTempDir, ourPathToKeep, false)) {
          File[] files = new File(myTempDir).listFiles();
          if (files != null) {
            for (File file : files) {
              if (!FileUtil.pathsEqual(file.getPath(), ourPathToKeep)) {
                FileUtil.delete(file);
              }
            }
          }
        } else {
          FileUtil.delete(new File(myTempDir));
        }
      }
    }

    UIUtil.removeLeakingAppleListeners();
    super.tearDown();
  }
  EditorsSplitters(
      final FileEditorManagerImpl manager,
      DockManager dockManager,
      boolean createOwnDockableContainer) {
    super(new BorderLayout());
    myManager = manager;
    myFocusWatcher = new MyFocusWatcher();
    setFocusTraversalPolicy(new MyFocusTraversalPolicy());
    clear();

    if (createOwnDockableContainer) {
      DockableEditorTabbedContainer dockable =
          new DockableEditorTabbedContainer(myManager.getProject(), this, false);
      Disposer.register(manager.getProject(), dockable);
      dockManager.register(dockable);
    }
    KeymapManagerListener keymapListener =
        new KeymapManagerListener() {
          @Override
          public void activeKeymapChanged(Keymap keymap) {
            invalidate();
            repaint();
          }
        };
    KeymapManager.getInstance().addKeymapManagerListener(keymapListener, this);
  }
  public LanguageConsoleImpl(
      Project project, String title, LightVirtualFile lightFile, boolean initComponents) {
    myProject = project;
    myTitle = title;
    myVirtualFile = lightFile;
    EditorFactory editorFactory = EditorFactory.getInstance();
    myHistoryFile = new LightVirtualFile(getTitle() + ".history.txt", FileTypes.PLAIN_TEXT, "");
    myEditorDocument = FileDocumentManager.getInstance().getDocument(lightFile);
    reparsePsiFile();
    assert myEditorDocument != null;
    myConsoleEditor = (EditorEx) editorFactory.createEditor(myEditorDocument, myProject);
    myConsoleEditor.addFocusListener(myFocusListener);
    myCurrentEditor = myConsoleEditor;
    myHistoryViewer =
        (EditorEx)
            editorFactory.createViewer(
                ((EditorFactoryImpl) editorFactory).createDocument(true), myProject);
    myUpdateQueue = new MergingUpdateQueue("ConsoleUpdateQueue", 300, true, null);
    Disposer.register(this, myUpdateQueue);

    // action shortcuts are not yet registered
    ApplicationManager.getApplication()
        .invokeLater(
            new Runnable() {
              @Override
              public void run() {
                installEditorFactoryListener();
              }
            });

    if (initComponents) {
      initComponents();
    }
  }
 @Override
 public void dispose() {
   saveLocation(getBounds());
   super.dispose();
   Disposer.dispose(myScreen);
   WelcomeFrame.resetInstance();
 }
 public void setTreeBuilder(final AbstractTreeBuilder treeBuilder) {
   if (treeBuilder != null) {
     Disposer.register(this, treeBuilder);
     // needs refactoring for project view first
     //      treeBuilder.setCanYieldUpdate(true);
   }
   myTreeBuilder = treeBuilder;
 }
 protected EditorTextFieldCellRenderer(
     @Nullable Project project,
     @Nullable FileType fileType,
     boolean inheritFontFromLaF,
     @NotNull Disposable parent) {
   myProject = project;
   myFileType = fileType;
   myInheritFontFromLaF = inheritFontFromLaF;
   Disposer.register(parent, this);
 }
 @Override
 public void dispose() {
   setRefreshVisible(false);
   InlineProgressIndicator[] indicators =
       getCurrentInlineIndicators().toArray(new InlineProgressIndicator[0]);
   for (InlineProgressIndicator indicator : indicators) {
     Disposer.dispose(indicator);
   }
   myInline2Original.clear();
   myOriginal2Inlines.clear();
 }
  public void dispose() {
    fireApplicationExiting();

    ShutDownTracker.getInstance().ensureStopperThreadsFinished();

    disposeComponents();

    ourThreadExecutorsService.shutdownNow();
    myComponentStore = null;
    super.dispose();
    Disposer.dispose(myLastDisposable); // dispose it last
  }
  @Override
  public void disposeComponent() {
    releaseEditor();
    myMappings.disposeMe();
    myConnect.disconnect();
    Disposer.dispose(myAnnotationLocalChangesListener);
    myContentManager = null;

    ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
    if (toolWindowManager != null && toolWindowManager.getToolWindow(ToolWindowId.VCS) != null) {
      toolWindowManager.unregisterToolWindow(ToolWindowId.VCS);
    }
  }
  @NotNull
  private RendererComponent getEditorPanel(final JTable table) {
    RendererComponent panel = UIUtil.getClientProperty(table, MY_PANEL_PROPERTY);
    if (panel != null) {
      DelegateColorScheme scheme = (DelegateColorScheme) panel.getEditor().getColorsScheme();
      scheme.setDelegate(EditorColorsManager.getInstance().getGlobalScheme());
      return panel;
    }

    panel = createRendererComponent(myProject, myFileType, myInheritFontFromLaF);
    Disposer.register(this, panel);
    Disposer.register(
        this,
        new Disposable() {
          @Override
          public void dispose() {
            UIUtil.putClientProperty(table, MY_PANEL_PROPERTY, null);
          }
        });

    table.putClientProperty(MY_PANEL_PROPERTY, panel);
    return panel;
  }
 private DiffPanel createPanel(final boolean horizontal) {
   final DiffPanel diffPanel =
       new DiffPanelImpl(null, myProject, false, horizontal) {
         @Override
         protected DiffPanelState createDiffPanelState(@NotNull Disposable parentDisposable) {
           return new FragmentedDiffPanelState(this, myProject, !horizontal, parentDisposable);
         }
       };
   diffPanel.enableToolbar(false);
   diffPanel.removeStatusBar();
   DiffPanelOptions o = ((DiffPanelEx) diffPanel).getOptions();
   o.setRequestFocusOnNewContent(false);
   Disposer.register(this, diffPanel);
   return diffPanel;
 }
Example #15
0
      private MyFocusCommand(DialogWrapper wrapper) {
        myWrapper = getDialogWrapper();
        setToInvalidateRequestors(false);

        Disposer.register(
            wrapper.getDisposable(),
            new Disposable() {
              @Override
              public void dispose() {
                if (!myTypeAheadDone.isProcessed()) {
                  myTypeAheadDone.setDone();
                }

                flushEvents();
              }
            });
      }
  public void cancel(InputEvent e) {
    if (isDisposed()) return;

    if (myPopup != null) {
      if (!canClose()) {
        return;
      }
      storeDimensionSize(myContent.getSize());
      if (myUseDimServiceForXYLocation) {
        final JRootPane root = myComponent.getRootPane();
        if (root != null) {
          final Container popupWindow = root.getParent();
          if (popupWindow != null && popupWindow.isShowing()) {
            storeLocation(popupWindow.getLocationOnScreen());
          }
        }
      }

      if (e instanceof MouseEvent) {
        IdeEventQueue.getInstance().blockNextEvents(((MouseEvent) e));
      }

      myPopup.hide(false);

      if (ApplicationManagerEx.getApplicationEx() != null) {
        StackingPopupDispatcher.getInstance().onPopupHidden(this);
      }

      if (myInStack) {
        myFocusTrackback.setForcedRestore(!myOk && myFocusable);
        myFocusTrackback.restoreFocus();
      }

      disposePopup();

      if (myListeners != null) {
        for (JBPopupListener each : myListeners) {
          each.onClosed(new LightweightWindowEvent(this, myOk));
        }
      }
    }

    Disposer.dispose(this, false);
  }
  public FlatWelcomeFrame() {
    final JRootPane rootPane = getRootPane();
    myScreen = new FlatWelcomeScreen();

    final IdeGlassPaneImpl glassPane =
        new IdeGlassPaneImpl(rootPane) {
          @Override
          public void addNotify() {
            super.addNotify();
            rootPane.remove(getProxyComponent());
            //noinspection SSBasedInspection
            SwingUtilities.invokeLater(
                new Runnable() {
                  public void run() {
                    JBProtocolCommand.handleCurrentCommand();
                  }
                });
          }
        };

    setGlassPane(glassPane);
    glassPane.setVisible(false);
    // setUndecorated(true);
    setContentPane(myScreen.getWelcomePanel());
    setTitle("Welcome to " + ApplicationNamesInfo.getInstance().getFullProductName());
    AppUIUtil.updateWindowIcon(this);
    final int width =
        RecentProjectsManager.getInstance().getRecentProjectsActions(false).length == 0 ? 666 : 777;
    setSize(JBUI.size(width, 460));
    setResizable(false);
    // int x = bounds.x + (bounds.width - getWidth()) / 2;
    // int y = bounds.y + (bounds.height - getHeight()) / 2;
    Point location = DimensionService.getInstance().getLocation(WelcomeFrame.DIMENSION_KEY, null);
    Rectangle screenBounds =
        ScreenUtil.getScreenRectangle(location != null ? location : new Point(0, 0));
    setLocation(
        new Point(
            screenBounds.x + (screenBounds.width - getWidth()) / 2,
            screenBounds.y + (screenBounds.height - getHeight()) / 3));

    // setLocation(x, y);
    ProjectManager.getInstance()
        .addProjectManagerListener(
            new ProjectManagerAdapter() {
              @Override
              public void projectOpened(Project project) {
                dispose();
              }
            });

    myBalloonLayout = new BalloonLayoutImpl(rootPane, JBUI.insets(8));

    WelcomeFrame.setupCloseAction(this);
    MnemonicHelper.init(this);
    Disposer.register(
        ApplicationManager.getApplication(),
        new Disposable() {
          @Override
          public void dispose() {
            FlatWelcomeFrame.this.dispose();
          }
        });
  }
 private void uninstallSynchronizer() {
   if (myMenuItemSynchronizer != null) {
     Disposer.dispose(myMenuItemSynchronizer);
     myMenuItemSynchronizer = null;
   }
 }
  public void show() {
    // final long time = System.currentTimeMillis();
    JComponent panel = createCenterPanel();
    new MnemonicHelper().register(panel);
    boolean shouldSetWidth =
        DimensionService.getInstance().getSize(getDimensionServiceKey(), myProject) == null;
    myPopup =
        JBPopupFactory.getInstance()
            .createComponentPopupBuilder(panel, null)
            .setTitle(myTitle)
            .setResizable(true)
            .setModalContext(false)
            .setFocusable(true)
            .setMovable(true)
            .setBelongsToGlobalPopupStack(true)
            // .setCancelOnClickOutside(false) //for debug and snapshots
            .setCancelKeyEnabled(false)
            .setDimensionServiceKey(null, getDimensionServiceKey(), false)
            .setCancelCallback(
                new Computable<Boolean>() {
                  @Override
                  public Boolean compute() {
                    DimensionService.getInstance()
                        .setLocation(
                            getDimensionServiceKey(), myPopup.getLocationOnScreen(), myProject);
                    return true;
                  }
                })
            .createPopup();

    myTree.addTreeSelectionListener(
        new TreeSelectionListener() {
          @Override
          public void valueChanged(TreeSelectionEvent e) {
            if (myPopup.isVisible()) {
              final PopupUpdateProcessor updateProcessor =
                  myPopup.getUserData(PopupUpdateProcessor.class);
              if (updateProcessor != null) {
                final AbstractTreeNode node = getSelectedNode();
                updateProcessor.updatePopup(node);
              }
            }
          }
        });
    Disposer.register(myPopup, this);
    Disposer.register(
        myPopup,
        new Disposable() {
          @Override
          public void dispose() {
            if (!myTreeHasBuilt.isDone()) {
              myTreeHasBuilt.setRejected();
            }
          }
        });
    myTree.getEmptyText().setText("Loading...");
    final Point location =
        DimensionService.getInstance().getLocation(getDimensionServiceKey(), myProject);
    if (location != null) {
      myPopup.showInScreenCoordinates(myEditor.getContentComponent(), location);
    } else {
      myPopup.showCenteredInCurrentWindow(myProject);
    }

    ((AbstractPopup) myPopup).setShowHints(true);
    if (shouldSetWidth) {
      myPopup.setSize(new Dimension(myPreferredWidth + 10, myPopup.getSize().height));
    }

    IdeFocusManager.getInstance(myProject).requestFocus(myTree, true);
    ApplicationManager.getApplication()
        .executeOnPooledThread(
            new Runnable() {
              @Override
              public void run() {
                final AccessToken token =
                    ApplicationManager.getApplication().acquireReadActionLock();
                try {
                  myFilteringStructure.rebuild();
                } finally {
                  token.finish();
                }

                SwingUtilities.invokeLater(
                    new Runnable() {
                      @Override
                      public void run() {
                        myAbstractTreeBuilder
                            .queueUpdate()
                            .doWhenDone(
                                new Runnable() {
                                  @Override
                                  public void run() {
                                    myTreeHasBuilt.setDone();
                                    //noinspection SSBasedInspection
                                    SwingUtilities.invokeLater(
                                        new Runnable() {
                                          @Override
                                          public void run() {
                                            selectPsiElement(myInitialPsiElement);
                                          }
                                        });
                                  }
                                });
                      }
                    });
                installUpdater();
              }
            });
  }
  public FileStructurePopup(
      StructureViewModel structureViewModel,
      @Nullable Editor editor,
      Project project,
      @NotNull final Disposable auxDisposable,
      final boolean applySortAndFilter) {
    myProject = project;
    myEditor = editor;

    // Stop code analyzer to speedup EDT
    final DaemonCodeAnalyzer analyzer = DaemonCodeAnalyzer.getInstance(myProject);
    if (analyzer != null) {
      myDaemonUpdateEnabled = ((DaemonCodeAnalyzerImpl) analyzer).isUpdateByTimerEnabled();
      analyzer.setUpdateByTimerEnabled(false);
    } else {
      myDaemonUpdateEnabled = false;
    }

    IdeFocusManager.getInstance(myProject).typeAheadUntil(myTreeHasBuilt);
    myBaseTreeModel = structureViewModel;
    Disposer.register(this, auxDisposable);
    if (applySortAndFilter) {
      myTreeActionsOwner = new TreeStructureActionsOwner(myBaseTreeModel);
      myTreeModel = new TreeModelWrapper(structureViewModel, myTreeActionsOwner);
    } else {
      myTreeActionsOwner = null;
      myTreeModel = structureViewModel;
    }

    myTreeStructure =
        new SmartTreeStructure(project, myTreeModel) {
          public void rebuildTree() {
            if (ApplicationManager.getApplication().isUnitTestMode() || !myPopup.isDisposed()) {
              super.rebuildTree();
            }
          }

          public boolean isToBuildChildrenInBackground(final Object element) {
            return getRootElement() == element;
          }

          protected TreeElementWrapper createTree() {
            return new StructureViewComponent.StructureViewTreeElementWrapper(
                myProject, myModel.getRoot(), myModel);
          }

          @Override
          public String toString() {
            return "structure view tree structure(model=" + myTreeModel + ")";
          }
        };

    myTree =
        new FileStructureTree(
            myTreeStructure.getRootElement(), Registry.is("fast.tree.expand.in.structure.view"));

    myTree.setCellRenderer(
        new NodeRenderer() {
          @Override
          protected void doAppend(
              @NotNull @Nls String fragment,
              @NotNull SimpleTextAttributes attributes,
              boolean isMainText,
              boolean selected) {
            SpeedSearchUtil.appendFragmentsForSpeedSearch(
                myTree, fragment, attributes, selected, this);
          }

          @Override
          public void doAppend(
              @NotNull String fragment,
              @NotNull SimpleTextAttributes attributes,
              boolean selected) {
            SpeedSearchUtil.appendFragmentsForSpeedSearch(
                myTree, fragment, attributes, selected, this);
          }

          @Override
          public void doAppend(String fragment, boolean selected) {
            SpeedSearchUtil.appendFragmentsForSpeedSearch(
                myTree, fragment, SimpleTextAttributes.REGULAR_ATTRIBUTES, selected, this);
          }
        });

    mySpeedSearch = new MyTreeSpeedSearch();
    mySpeedSearch.setComparator(new SpeedSearchComparator(false, true));

    final FileStructurePopupFilter filter = new FileStructurePopupFilter();
    myFilteringStructure =
        new FilteringTreeStructure(
            filter, myTreeStructure, ApplicationManager.getApplication().isUnitTestMode());
    myAbstractTreeBuilder =
        new FilteringTreeBuilder(myTree, filter, myFilteringStructure, null) {
          @Override
          public void initRootNode() {}

          @Override
          protected boolean validateNode(Object child) {
            return StructureViewComponent.isValid(child);
          }

          @Override
          public void revalidateTree() {
            // myTree.revalidate();
            // myTree.repaint();
          }

          @Override
          public boolean isToEnsureSelectionOnFocusGained() {
            return false;
          }
        };

    myTreeExpander = new DefaultTreeExpander(myTree);

    // myAbstractTreeBuilder.getUi().setPassthroughMode(true);
    myAbstractTreeBuilder.getUi().getUpdater().setDelay(1);
    myInitialPsiElement = getCurrentElement(getPsiFile(myProject));
    // myAbstractTreeBuilder.setCanYieldUpdate(true);
    Disposer.register(this, myAbstractTreeBuilder);
  }
 protected <T extends Disposable> T disposeOnTearDown(final T disposable) {
   Disposer.register(myTestRootDisposable, disposable);
   return disposable;
 }
 public void navigate(int injectedOffset) {
   if (myAction.isShowInBalloon()) {
     final JComponent component = myAction.createBalloonComponent(myNewFile);
     if (component != null) {
       final Balloon balloon =
           JBPopupFactory.getInstance()
               .createBalloonBuilder(component)
               .setShadow(true)
               .setAnimationCycle(0)
               .setHideOnClickOutside(true)
               .setHideOnKeyOutside(true)
               .setHideOnAction(false)
               .setFillColor(UIUtil.getControlColor())
               .createBalloon();
       new AnAction() {
         @Override
         public void actionPerformed(AnActionEvent e) {
           balloon.hide();
         }
       }.registerCustomShortcutSet(CommonShortcuts.ESCAPE, component);
       Disposer.register(myNewFile.getProject(), balloon);
       final Balloon.Position position = QuickEditAction.getBalloonPosition(myEditor);
       RelativePoint point = JBPopupFactory.getInstance().guessBestPopupLocation(myEditor);
       if (position == Balloon.Position.above) {
         final Point p = point.getPoint();
         point =
             new RelativePoint(
                 point.getComponent(), new Point(p.x, p.y - myEditor.getLineHeight()));
       }
       balloon.show(point, position);
     }
   } else {
     final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(myProject);
     final FileEditor[] editors = fileEditorManager.getEditors(myNewVirtualFile);
     if (editors.length == 0) {
       final EditorWindow curWindow = fileEditorManager.getCurrentWindow();
       mySplittedWindow =
           curWindow.split(SwingConstants.HORIZONTAL, false, myNewVirtualFile, true);
     }
     Editor editor =
         fileEditorManager.openTextEditor(
             new OpenFileDescriptor(myProject, myNewVirtualFile, injectedOffset), true);
     // fold missing values
     if (editor != null) {
       editor.putUserData(QuickEditAction.QUICK_EDIT_HANDLER, this);
       final FoldingModel foldingModel = editor.getFoldingModel();
       foldingModel.runBatchFoldingOperation(
           () -> {
             for (RangeMarker o :
                 ContainerUtil.reverse(((DocumentEx) myNewDocument).getGuardedBlocks())) {
               String replacement = o.getUserData(REPLACEMENT_KEY);
               if (StringUtil.isEmpty(replacement)) continue;
               FoldRegion region =
                   foldingModel.addFoldRegion(o.getStartOffset(), o.getEndOffset(), replacement);
               if (region != null) region.setExpanded(false);
             }
           });
     }
     SwingUtilities.invokeLater(
         () -> myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE));
   }
 }
  public void dispose() {
    if (myDisposed) {
      return;
    }
    myDisposed = true;

    Disposer.dispose(this, false);

    assert ApplicationManager.getApplication().isDispatchThread();

    if (myPopup != null) {
      cancel(myDisposeEvent);
    }

    if (myContent != null) {
      myContent.removeAll();
      myContent.removeKeyListener(mySearchKeyListener);
    }
    myContent = null;
    myPreferredFocusedComponent = null;
    myComponent = null;
    myFocusTrackback = null;
    myCallBack = null;
    myListeners = null;

    if (myMouseOutCanceller != null) {
      final Toolkit toolkit = Toolkit.getDefaultToolkit();
      // it may happen, but have no idea how
      // http://www.jetbrains.net/jira/browse/IDEADEV-21265
      if (toolkit != null) {
        toolkit.removeAWTEventListener(myMouseOutCanceller);
      }
    }
    myMouseOutCanceller = null;

    if (myFocusWatcher != null) {
      myFocusWatcher.dispose();
      myFocusWatcher = null;
    }

    resetWindow();

    if (myFinalRunnable != null) {
      final ActionCallback typeaheadDone = new ActionCallback();
      Runnable runFinal =
          new Runnable() {
            @Override
            public void run() {
              SwingUtilities.invokeLater(
                  new Runnable() {
                    @Override
                    public void run() {
                      typeaheadDone.setDone();
                    }
                  });
              myFinalRunnable.run();
              myFinalRunnable = null;
            }
          };

      IdeFocusManager.getInstance(myProject).typeAheadUntil(typeaheadDone);
      getFocusManager().doWhenFocusSettlesDown(runFinal);
    }
  }
  private void buildInInlineIndicator(@NotNull final InlineProgressIndicator inline) {
    removeAll();
    setLayout(new InlineLayout());
    add(myRefreshAndInfoPanel);

    final JPanel inlinePanel = new JPanel(new BorderLayout());

    inline.getComponent().setBorder(new EmptyBorder(1, 0, 0, 2));
    final JComponent inlineComponent = inline.getComponent();
    inlineComponent.setOpaque(false);
    inlinePanel.add(inlineComponent, BorderLayout.CENTER);

    // myProgressIcon.setBorder(new IdeStatusBarImpl.MacStatusBarWidgetBorder());
    inlinePanel.add(myProgressIcon, BorderLayout.WEST);

    inline.updateProgressNow();
    inlinePanel.setOpaque(false);

    add(inlinePanel);

    myRefreshAndInfoPanel.revalidate();
    myRefreshAndInfoPanel.repaint();

    if (UISettings.getInstance().PRESENTATION_MODE) {
      final JRootPane pane = myInfoPanel.getRootPane();
      final RelativePoint point = new RelativePoint(pane, new Point(pane.getWidth() - 250, 60));
      final PresentationModeProgressPanel panel = new PresentationModeProgressPanel(inline);
      final MyInlineProgressIndicator delegate =
          new MyInlineProgressIndicator(true, inline.getInfo(), inline) {
            @Override
            protected void updateProgress() {
              super.updateProgress();
              panel.update();
            }
          };

      Disposer.register(inline, delegate);

      JBPopupFactory.getInstance()
          .createBalloonBuilder(panel.getRootPanel())
          .setFadeoutTime(0)
          .setFillColor(Gray.TRANSPARENT)
          .setShowCallout(false)
          .setBorderColor(Gray.TRANSPARENT)
          .setBorderInsets(new Insets(0, 0, 0, 0))
          .setAnimationCycle(0)
          .setCloseButtonEnabled(false)
          .setHideOnClickOutside(false)
          .setDisposable(inline)
          .setHideOnFrameResize(false)
          .setHideOnKeyOutside(false)
          .setBlockClicksThroughBalloon(true)
          .setHideOnAction(false)
          .createBalloon()
          .show(
              new PositionTracker<Balloon>(pane) {
                @Override
                public RelativePoint recalculateLocation(Balloon object) {
                  final EditorComponentImpl editorComponent =
                      UIUtil.findComponentOfType(pane, EditorComponentImpl.class);
                  if (editorComponent != null) {
                    return new RelativePoint(
                        editorComponent.getParent().getParent(),
                        new Point(
                            editorComponent.getParent().getParent().getWidth() - 150,
                            editorComponent.getParent().getParent().getHeight() - 70));
                  }
                  return point;
                }
              },
              Balloon.Position.above);
    }
  }
  public void show(Component owner, int aScreenX, int aScreenY, final boolean considerForcedXY) {
    if (ApplicationManagerEx.getApplicationEx() != null
        && ApplicationManager.getApplication().isHeadlessEnvironment()) return;
    if (isDisposed()) {
      throw new IllegalStateException(
          "Popup was already disposed. Recreate a new instance to show again");
    }

    assert ApplicationManager.getApplication().isDispatchThread();

    addActivity();

    final boolean shouldShow = beforeShow();
    if (!shouldShow) {
      removeActivity();
      return;
    }

    prepareToShow();

    if (myInStack) {
      myFocusTrackback = new FocusTrackback(this, owner, true);
      myFocusTrackback.setMustBeShown(true);
    }

    Dimension sizeToSet = null;

    if (myDimensionServiceKey != null) {
      sizeToSet = DimensionService.getInstance().getSize(myDimensionServiceKey, myProject);
    }

    if (myForcedSize != null) {
      sizeToSet = myForcedSize;
    }

    if (myMinSize == null) {
      myMinSize = myContent.getMinimumSize();
    }

    if (sizeToSet == null) {
      sizeToSet = myContent.getPreferredSize();
    }

    if (sizeToSet != null) {
      sizeToSet.width = Math.max(sizeToSet.width, myMinSize.width);
      sizeToSet.height = Math.max(sizeToSet.height, myMinSize.height);

      myContent.setSize(sizeToSet);
      myContent.setPreferredSize(sizeToSet);
    }

    Point xy = new Point(aScreenX, aScreenY);
    boolean adjustXY = true;
    if (myDimensionServiceKey != null) {
      final Point storedLocation =
          DimensionService.getInstance().getLocation(myDimensionServiceKey, myProject);
      if (storedLocation != null) {
        xy = storedLocation;
        adjustXY = false;
      }
    }

    if (adjustXY) {
      final Insets insets = myContent.getInsets();
      if (insets != null) {
        xy.x -= insets.left;
        xy.y -= insets.top;
      }
    }

    if (considerForcedXY && myForcedLocation != null) {
      xy = myForcedLocation;
    }

    if (myLocateByContent) {
      final Dimension captionSize = myHeaderPanel.getPreferredSize();
      xy.y -= captionSize.height;
    }

    Rectangle targetBounds = new Rectangle(xy, myContent.getPreferredSize());
    Insets insets = myPopupBorder.getBorderInsets(myContent);
    if (insets != null) {
      targetBounds.x += insets.left;
      targetBounds.y += insets.top;
    }

    Rectangle original = new Rectangle(targetBounds);
    if (myLocateWithinScreen) {
      ScreenUtil.moveRectangleToFitTheScreen(targetBounds);
    }

    if (myMouseOutCanceller != null) {
      myMouseOutCanceller.myEverEntered = targetBounds.equals(original);
    }

    myOwner = IdeFrameImpl.findNearestModalComponent(owner);
    if (myOwner == null) {
      myOwner = owner;
    }

    myRequestorComponent = owner;

    boolean forcedDialog = (SystemInfo.isMac && !(myOwner instanceof IdeFrame)) || myMayBeParent;

    PopupComponent.Factory factory = getFactory(myForcedHeavyweight || myResizable, forcedDialog);
    myNativePopup = factory.isNativePopup();
    myPopup = factory.getPopup(myOwner, myContent, targetBounds.x, targetBounds.y);

    if (myResizable) {
      final JRootPane root = myContent.getRootPane();
      final IdeGlassPaneImpl glass = new IdeGlassPaneImpl(root);
      root.setGlassPane(glass);

      final ResizeComponentListener resizeListener = new ResizeComponentListener(this, glass);
      glass.addMousePreprocessor(resizeListener, this);
      glass.addMouseMotionPreprocessor(resizeListener, this);
    }

    if (myCaption != null && myMovable) {
      final MoveComponentListener moveListener =
          new MoveComponentListener(myCaption) {
            public void mousePressed(final MouseEvent e) {
              super.mousePressed(e);
              if (e.isConsumed()) return;

              if (UIUtil.isCloseClick(e)) {
                if (myCaption.isWithinPanel(e)) {
                  cancel();
                }
              }
            }
          };
      ListenerUtil.addMouseListener(myCaption, moveListener);
      ListenerUtil.addMouseMotionListener(myCaption, moveListener);
      final MyContentPanel saved = myContent;
      Disposer.register(
          this,
          new Disposable() {
            public void dispose() {
              ListenerUtil.removeMouseListener(saved, moveListener);
              ListenerUtil.removeMouseMotionListener(saved, moveListener);
            }
          });
    }

    for (JBPopupListener listener : myListeners) {
      listener.beforeShown(new LightweightWindowEvent(this));
    }

    myPopup.setRequestFocus(myRequestFocus);
    myPopup.show();

    final Window window = SwingUtilities.getWindowAncestor(myContent);

    myWindowListener = new MyWindowListener();
    window.addWindowListener(myWindowListener);

    if (myFocusable) {
      window.setFocusableWindowState(true);
      window.setFocusable(true);
    }

    myWindow = updateMaskAndAlpha(window);

    if (myWindow instanceof JWindow) {
      ((JWindow) myWindow).getRootPane().putClientProperty(KEY, this);
    }

    if (myWindow != null) {
      // dialogwrapper-based popups do this internally through peer,
      // for other popups like jdialog-based we should exclude them manually, but
      // we still have to be able to use IdeFrame as parent
      if (!myMayBeParent && !(myWindow instanceof Frame)) {
        WindowManager.getInstance().doNotSuggestAsParent(myWindow);
      }
    }

    final Runnable afterShow =
        new Runnable() {
          public void run() {
            if (myPreferredFocusedComponent != null && myInStack && myFocusable) {
              myFocusTrackback.registerFocusComponent(myPreferredFocusedComponent);
            }

            removeActivity();

            afterShow();
          }
        };

    if (myRequestFocus) {
      getFocusManager()
          .requestFocus(
              new FocusCommand() {
                @Override
                public ActionCallback run() {
                  if (isDisposed()) {
                    removeActivity();
                    return new ActionCallback.Done();
                  }

                  _requestFocus();

                  final ActionCallback result = new ActionCallback();

                  final Runnable afterShowRunnable =
                      new Runnable() {
                        @Override
                        public void run() {
                          afterShow.run();
                          result.setDone();
                        }
                      };
                  if (myNativePopup) {
                    final FocusRequestor furtherRequestor = getFocusManager().getFurtherRequestor();
                    SwingUtilities.invokeLater(
                        new Runnable() {
                          @Override
                          public void run() {
                            if (isDisposed()) {
                              result.setRejected();
                              return;
                            }

                            furtherRequestor
                                .requestFocus(
                                    new FocusCommand() {
                                      @Override
                                      public ActionCallback run() {
                                        if (isDisposed()) {
                                          return new ActionCallback.Rejected();
                                        }

                                        _requestFocus();

                                        afterShowRunnable.run();

                                        return new ActionCallback.Done();
                                      }
                                    },
                                    true)
                                .notify(result)
                                .doWhenProcessed(
                                    new Runnable() {
                                      @Override
                                      public void run() {
                                        removeActivity();
                                      }
                                    });
                          }
                        });
                  } else {
                    afterShowRunnable.run();
                  }

                  return result;
                }
              },
              true)
          .doWhenRejected(
              new Runnable() {
                @Override
                public void run() {
                  afterShow.run();
                }
              });
    } else {
      SwingUtilities.invokeLater(
          new Runnable() {
            @Override
            public void run() {
              if (isDisposed()) {
                removeActivity();
                return;
              }

              afterShow.run();
            }
          });
    }
  }
  private void prepareToShow() {
    final MouseAdapter mouseAdapter =
        new MouseAdapter() {
          public void mousePressed(MouseEvent e) {
            Point point = (Point) e.getPoint().clone();
            SwingUtilities.convertPointToScreen(point, e.getComponent());

            final Dimension dimension = myContent.getSize();
            dimension.height +=
                myResizable && isToDrawMacCorner() ? ourMacCorner.getHeight(myContent) : 4;
            dimension.width += 4;
            Point locationOnScreen = myContent.getLocationOnScreen();
            final Rectangle bounds =
                new Rectangle(new Point(locationOnScreen.x - 2, locationOnScreen.y - 2), dimension);
            if (!bounds.contains(point)) {
              cancel();
            }
          }
        };
    myContent.addMouseListener(mouseAdapter);
    Disposer.register(
        this,
        new Disposable() {
          public void dispose() {
            myContent.removeMouseListener(mouseAdapter);
          }
        });

    myContent.registerKeyboardAction(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (myCancelKeyEnabled) {
              cancel();
            }
          }
        },
        KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
        JComponent.WHEN_IN_FOCUSED_WINDOW);

    mySearchKeyListener = new SpeedSearchKeyListener();
    myContent.addKeyListener(mySearchKeyListener);

    if (myCancelOnMouseOutCallback != null || myCancelOnWindow) {
      myMouseOutCanceller = new Canceller();
      Toolkit.getDefaultToolkit()
          .addAWTEventListener(
              myMouseOutCanceller,
              AWTEvent.MOUSE_EVENT_MASK
                  | WindowEvent.WINDOW_ACTIVATED
                  | AWTEvent.MOUSE_MOTION_EVENT_MASK);
    }

    myFocusWatcher =
        new ChildFocusWatcher(myContent) {
          protected void onFocusGained(final FocusEvent event) {
            setWindowActive(true);
          }

          protected void onFocusLost(final FocusEvent event) {
            setWindowActive(false);
          }
        };

    mySpeedSearchPatternField = new JTextField();
    if (SystemInfo.isMac) {
      Font f = mySpeedSearchPatternField.getFont();
      mySpeedSearchPatternField.setFont(f.deriveFont(f.getStyle(), f.getSize() - 2));
    }
  }
  public ApplicationImpl(
      boolean isInternal,
      boolean isUnitTestMode,
      boolean isHeadless,
      boolean isCommandLine,
      @NotNull String appName) {
    super(null);

    getPicoContainer().registerComponentInstance(Application.class, this);

    CommonBundle.assertKeyIsFound = isUnitTestMode;

    if ((isInternal || isUnitTestMode)
        && !Comparing.equal("off", System.getProperty("idea.disposer.debug"))) {
      Disposer.setDebugMode(true);
    }
    myStartTime = System.currentTimeMillis();
    myName = appName;
    ApplicationManagerEx.setApplication(this);

    PluginsFacade.INSTANCE =
        new PluginsFacade() {
          public IdeaPluginDescriptor getPlugin(PluginId id) {
            return PluginManager.getPlugin(id);
          }

          public IdeaPluginDescriptor[] getPlugins() {
            return PluginManager.getPlugins();
          }
        };

    if (!isUnitTestMode && !isHeadless) {
      Toolkit.getDefaultToolkit().getSystemEventQueue().push(IdeEventQueue.getInstance());
      if (Patches.SUN_BUG_ID_6209673) {
        RepaintManager.setCurrentManager(new IdeRepaintManager());
      }
      IconLoader.activate();
    }

    myIsInternal = isInternal;
    myTestModeFlag = isUnitTestMode;
    myHeadlessMode = isHeadless;
    myCommandLineMode = isCommandLine;

    loadApplicationComponents();

    if (myTestModeFlag) {
      registerShutdownHook();
    }

    if (!isUnitTestMode && !isHeadless) {
      Disposer.register(this, Disposer.newDisposable(), "ui");

      StartupUtil.addExternalInstanceListener(
          new Consumer<List<String>>() {
            @Override
            public void consume(final List<String> args) {
              invokeLater(
                  new Runnable() {
                    @Override
                    public void run() {
                      final Project project = CommandLineProcessor.processExternalCommandLine(args);
                      final IdeFrame frame;
                      if (project != null) {
                        frame = WindowManager.getInstance().getIdeFrame(project);
                      } else {
                        frame = WindowManager.getInstance().getAllFrames()[0];
                      }
                      ((IdeFrameImpl) frame).requestFocus();
                    }
                  });
            }
          });
    }

    final String s = System.getProperty("jb.restart.code");
    if (s != null) {
      try {
        myRestartCode = Integer.parseInt(s);
      } catch (NumberFormatException ignore) {
      }
    }
  }
  public StructureViewComponent(
      final FileEditor editor,
      final StructureViewModel structureViewModel,
      final Project project,
      final boolean showRootNode) {
    super(true, true);

    myProject = project;
    myFileEditor = editor;
    myTreeModel = structureViewModel;
    myTreeModelWrapper = new TreeModelWrapper(myTreeModel, this);

    SmartTreeStructure treeStructure =
        new SmartTreeStructure(project, myTreeModelWrapper) {
          public void rebuildTree() {
            if (!isDisposed()) {
              super.rebuildTree();
            }
          }

          public boolean isToBuildChildrenInBackground(final Object element) {
            return getRootElement() == element;
          }

          protected TreeElementWrapper createTree() {
            return new StructureViewTreeElementWrapper(myProject, myModel.getRoot(), myModel);
          }

          @Override
          public String toString() {
            return "structure view tree structure(model=" + myTreeModel + ")";
          }
        };

    final DefaultTreeModel model =
        new DefaultTreeModel(new DefaultMutableTreeNode(treeStructure.getRootElement()));
    myTree = new Tree(model);
    myTree.setRootVisible(showRootNode);
    myTree.setShowsRootHandles(true);

    myAbstractTreeBuilder =
        new StructureTreeBuilder(
            project,
            myTree,
            (DefaultTreeModel) myTree.getModel(),
            treeStructure,
            myTreeModelWrapper) {
          @Override
          protected boolean validateNode(Object child) {
            return isValid(child);
          }
        };
    Disposer.register(this, myAbstractTreeBuilder);
    Disposer.register(
        myAbstractTreeBuilder,
        new Disposable() {
          public void dispose() {
            storeState();
          }
        });

    setContent(ScrollPaneFactory.createScrollPane(myAbstractTreeBuilder.getTree()));

    myAbstractTreeBuilder.getTree().setCellRenderer(new NodeRenderer());

    myAutoScrollToSourceHandler = new MyAutoScrollToSourceHandler();
    myAutoScrollFromSourceHandler = new MyAutoScrollFromSourceHandler(myProject, this);

    JComponent toolbarComponent =
        ActionManager.getInstance()
            .createActionToolbar(ActionPlaces.STRUCTURE_VIEW_TOOLBAR, createActionGroup(), true)
            .getComponent();
    setToolbar(toolbarComponent);

    installTree();

    myCopyPasteDelegator =
        new CopyPasteDelegator(myProject, getTree()) {
          @NotNull
          protected PsiElement[] getSelectedElements() {
            return getSelectedPsiElements();
          }
        };
  }
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
public class ApplicationImpl extends ComponentManagerImpl implements ApplicationEx {
  private static final Logger LOG =
      Logger.getInstance("#com.intellij.application.impl.ApplicationImpl");
  private final ModalityState MODALITY_STATE_NONE = ModalityState.NON_MODAL;
  private final ModalityInvokator myInvokator = new ModalityInvokatorImpl();

  private final EventDispatcher<ApplicationListener> myDispatcher =
      EventDispatcher.create(ApplicationListener.class);

  private IApplicationStore myComponentStore;

  private boolean myTestModeFlag;
  private final boolean myHeadlessMode;
  private final boolean myCommandLineMode;

  private final boolean myIsInternal;
  private final String myName;

  private final ReentrantWriterPreferenceReadWriteLock myActionsLock =
      new ReentrantWriterPreferenceReadWriteLock();
  private final Stack<Class> myWriteActionsStack =
      new Stack<Class>(); // accessed from EDT only, no need to sync

  private volatile Runnable myExceptionalThreadWithReadAccessRunnable;

  private int myInEditorPaintCounter = 0;
  private long myStartTime = 0;
  @Nullable private Splash mySplash;
  private boolean myDoNotSave;
  private volatile boolean myDisposeInProgress = false;

  private int myRestartCode = 0;
  private volatile int myExitCode = 0;
  private final Disposable myLastDisposable = Disposer.newDisposable(); // will be disposed last

  private final AtomicBoolean mySaveSettingsIsInProgress = new AtomicBoolean(false);

  @SuppressWarnings({"UseOfArchaicSystemPropertyAccessors"})
  private static final int ourDumpThreadsOnLongWriteActionWaiting =
      Integer.getInteger("dump.threads.on.long.write.action.waiting", 0);

  private final ExecutorService ourThreadExecutorsService =
      new ThreadPoolExecutor(
          3,
          Integer.MAX_VALUE,
          5 * 60L,
          TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(),
          new ThreadFactory() {
            int i;

            public Thread newThread(Runnable r) {
              final Thread thread =
                  new Thread(r, "ApplicationImpl pooled thread " + i++) {
                    public void interrupt() {
                      if (LOG.isDebugEnabled()) {
                        LOG.debug("Interrupted worker, will remove from pool");
                      }
                      super.interrupt();
                    }

                    public void run() {
                      try {
                        super.run();
                      } catch (Throwable t) {
                        if (LOG.isDebugEnabled()) {
                          LOG.debug("Worker exits due to exception", t);
                        }
                      }
                    }
                  };
              thread.setPriority(Thread.NORM_PRIORITY - 1);
              return thread;
            }
          });
  private boolean myIsFiringLoadingEvent = false;
  @NonNls private static final String WAS_EVER_SHOWN = "was.ever.shown";

  private Boolean myActive;

  private static final ThreadLocal<Integer> ourEdtSafe = new ThreadLocal<Integer>();
  private static final ModalityState ANY =
      new ModalityState() {
        @Override
        public boolean dominates(@NotNull ModalityState anotherState) {
          return false;
        }

        @Override
        public String toString() {
          return "ANY";
        }
      };

  protected void bootstrapPicoContainer() {
    super.bootstrapPicoContainer();
    getPicoContainer()
        .registerComponentImplementation(
            IComponentStore.class, StoresFactory.getApplicationStoreClass());
    getPicoContainer().registerComponentImplementation(ApplicationPathMacroManager.class);
  }

  @NotNull
  public synchronized IApplicationStore getStateStore() {
    if (myComponentStore == null) {
      myComponentStore =
          (IApplicationStore) getPicoContainer().getComponentInstance(IComponentStore.class);
    }
    return myComponentStore;
  }

  @Override
  public void initializeComponent(Object component, boolean service) {
    getStateStore().initComponent(component, service);
  }

  public ApplicationImpl(
      boolean isInternal,
      boolean isUnitTestMode,
      boolean isHeadless,
      boolean isCommandLine,
      @NotNull String appName,
      Splash splash) {
    super(null);

    ApplicationManagerEx.setApplication(
        this, myLastDisposable); // reset back to null only when all components already disposed

    getPicoContainer().registerComponentInstance(Application.class, this);

    CommonBundle.assertKeyIsFound = isUnitTestMode;
    AWTExceptionHandler.register(); // do not crash AWT on exceptions
    if ((isInternal || isUnitTestMode)
        && !Comparing.equal("off", System.getProperty("idea.disposer.debug"))) {
      Disposer.setDebugMode(true);
    }
    myStartTime = System.currentTimeMillis();
    mySplash = splash;
    myName = appName;

    PluginsFacade.INSTANCE =
        new PluginsFacade() {
          public IdeaPluginDescriptor getPlugin(PluginId id) {
            return PluginManager.getPlugin(id);
          }

          public IdeaPluginDescriptor[] getPlugins() {
            return PluginManager.getPlugins();
          }
        };

    myIsInternal = isInternal;
    myTestModeFlag = isUnitTestMode;
    myHeadlessMode = isHeadless;
    myCommandLineMode = isCommandLine;

    myDoNotSave = myTestModeFlag || myHeadlessMode;

    loadApplicationComponents();

    if (myTestModeFlag) {
      registerShutdownHook();
    }

    if (!isUnitTestMode && !isHeadless) {
      Disposer.register(this, Disposer.newDisposable(), "ui");

      StartupUtil.addExternalInstanceListener(
          new Consumer<List<String>>() {
            @Override
            public void consume(final List<String> args) {
              invokeLater(
                  new Runnable() {
                    @Override
                    public void run() {
                      final Project project = CommandLineProcessor.processExternalCommandLine(args);
                      final IdeFrame frame;
                      if (project != null) {
                        frame = WindowManager.getInstance().getIdeFrame(project);
                      } else {
                        frame = WindowManager.getInstance().getAllFrames()[0];
                      }
                      ((IdeFrameImpl) frame).requestFocus();
                    }
                  });
            }
          });
    }

    final String s = System.getProperty("jb.restart.code");
    if (s != null) {
      try {
        myRestartCode = Integer.parseInt(s);
      } catch (NumberFormatException ignore) {
      }
    }

    registerFont("/fonts/Inconsolata.ttf");
  }

  private void registerFont(String name) {
    if (isHeadlessEnvironment()) return;

    InputStream is = null;
    try {
      is = getClass().getResourceAsStream(name);
      final Font font = Font.createFont(Font.TRUETYPE_FONT, is);
      GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font);
    } catch (Exception e) {
      LOG.info(e);
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException e) {
          LOG.error(e);
        }
      }
    }
  }

  private void registerShutdownHook() {
    ShutDownTracker
        .getInstance(); // Necessary to avoid creating an instance while already shutting down.

    ShutDownTracker.getInstance()
        .registerShutdownTask(
            new Runnable() {
              public void run() {
                if (isDisposed() || isDisposeInProgress()) {
                  return;
                }
                ShutDownTracker.invokeAndWait(
                    isUnitTestMode(),
                    new Runnable() {
                      public void run() {
                        if (ApplicationManager.getApplication() != ApplicationImpl.this) return;
                        try {
                          myDisposeInProgress = true;
                          saveAll();
                        } finally {
                          disposeSelf();
                        }
                      }
                    });
              }
            });
  }

  private boolean disposeSelf() {
    final CommandProcessor commandProcessor = CommandProcessor.getInstance();
    final Ref<Boolean> canClose = new Ref<Boolean>(Boolean.TRUE);
    for (final Project project : ProjectManagerEx.getInstanceEx().getOpenProjects()) {
      try {
        commandProcessor.executeCommand(
            project,
            new Runnable() {
              public void run() {
                canClose.set(ProjectUtil.closeAndDispose(project));
              }
            },
            ApplicationBundle.message("command.exit"),
            null);
      } catch (Throwable e) {
        LOG.error(e);
      }
      if (!canClose.get()) {
        myDisposeInProgress = false;
        return false;
      }
    }
    Disposer.dispose(this);

    Disposer.assertIsEmpty();
    return true;
  }

  @NotNull
  public String getName() {
    return myName;
  }

  public boolean holdsReadLock() {
    return myActionsLock.isReadLockAcquired();
  }

  @Override
  protected void handleInitComponentError(
      final Throwable ex, final boolean fatal, final String componentClassName) {
    if (PluginManager.isPluginClass(componentClassName)) {
      LOG.error(ex);
      PluginId pluginId = PluginManager.getPluginByClassName(componentClassName);
      @NonNls
      final String errorMessage =
          "Plugin "
              + pluginId.getIdString()
              + " failed to initialize and will be disabled:\n"
              + ex.getMessage()
              + "\nPlease restart "
              + ApplicationNamesInfo.getInstance().getFullProductName()
              + ".";
      PluginManager.disablePlugin(pluginId.getIdString());
      if (!myHeadlessMode) {
        JOptionPane.showMessageDialog(null, errorMessage);
      } else {
        //noinspection UseOfSystemOutOrSystemErr
        System.out.println(errorMessage);
        System.exit(1);
      }
      return; // do not call super
    }
    if (fatal) {
      LOG.error(ex);
      @NonNls
      final String errorMessage =
          "Fatal error initializing class "
              + componentClassName
              + ":\n"
              + ex.toString()
              + "\nComplete error stacktrace was written to idea.log";
      if (!myHeadlessMode) {
        JOptionPane.showMessageDialog(null, errorMessage);
      } else {
        //noinspection UseOfSystemOutOrSystemErr
        System.out.println(errorMessage);
      }
    }
    super.handleInitComponentError(ex, fatal, componentClassName);
  }

  private void loadApplicationComponents() {
    PluginManager.initPlugins(mySplash);
    final IdeaPluginDescriptor[] plugins = PluginManager.getPlugins();
    for (IdeaPluginDescriptor plugin : plugins) {
      if (PluginManager.shouldSkipPlugin(plugin)) continue;
      loadComponentsConfiguration(plugin.getAppComponents(), plugin, false);
    }
  }

  @Override
  protected synchronized Object createComponent(Class componentInterface) {
    Object component = super.createComponent(componentInterface);
    if (mySplash != null) {
      mySplash.showProgress(
          "", (float) (0.65f + myComponentsRegistry.getPercentageOfComponentsLoaded() * 0.35f));
    }
    return component;
  }

  protected MutablePicoContainer createPicoContainer() {
    return Extensions.getRootArea().getPicoContainer();
  }

  public boolean isInternal() {
    return myIsInternal;
  }

  public boolean isUnitTestMode() {
    return myTestModeFlag;
  }

  public void setUnitTestMode(boolean testModeFlag) {
    myTestModeFlag = testModeFlag;
  }

  public boolean isHeadlessEnvironment() {
    return myHeadlessMode;
  }

  public boolean isCommandLine() {
    return myCommandLineMode;
  }

  public Future<?> executeOnPooledThread(@NotNull final Runnable action) {
    return ourThreadExecutorsService.submit(
        new Runnable() {
          public void run() {
            try {
              action.run();
            } catch (ProcessCanceledException e) {
              // ignore
            } catch (Throwable t) {
              LOG.error(t);
            } finally {
              Thread.interrupted(); // reset interrupted status
            }
          }
        });
  }

  @Override
  public <T> Future<T> executeOnPooledThread(@NotNull final Callable<T> action) {
    return ourThreadExecutorsService.submit(
        new Callable<T>() {
          public T call() {
            try {
              return action.call();
            } catch (ProcessCanceledException e) {
              // ignore
            } catch (Throwable t) {
              LOG.error(t);
            } finally {
              Thread.interrupted(); // reset interrupted status
            }
            return null;
          }
        });
  }

  private static Thread ourDispatchThread = null;

  public boolean isDispatchThread() {
    return EventQueue.isDispatchThread();
  }

  @NotNull
  public ModalityInvokator getInvokator() {
    return myInvokator;
  }

  public void invokeLater(@NotNull final Runnable runnable) {
    myInvokator.invokeLater(runnable);
  }

  public void invokeLater(@NotNull final Runnable runnable, @NotNull final Condition expired) {
    myInvokator.invokeLater(runnable, expired);
  }

  public void invokeLater(@NotNull final Runnable runnable, @NotNull final ModalityState state) {
    myInvokator.invokeLater(runnable, state);
  }

  public void invokeLater(
      @NotNull final Runnable runnable,
      @NotNull final ModalityState state,
      @NotNull final Condition expired) {
    myInvokator.invokeLater(runnable, state, expired);
  }

  public void load(String path) throws IOException, InvalidDataException {
    getStateStore().setOptionsPath(path);
    getStateStore().setConfigPath(PathManager.getConfigPath());
    myIsFiringLoadingEvent = true;
    try {
      fireBeforeApplicationLoaded();
    } finally {
      myIsFiringLoadingEvent = false;
    }

    loadComponentRoamingTypes();

    HeavyProcessLatch.INSTANCE.processStarted();
    try {
      getStateStore().load();
    } catch (StateStorageException e) {
      throw new IOException(e.getMessage());
    } finally {
      HeavyProcessLatch.INSTANCE.processFinished();
    }
  }

  @Override
  protected <T> T getComponentFromContainer(final Class<T> interfaceClass) {
    if (myIsFiringLoadingEvent) {
      return null;
    }
    return super.getComponentFromContainer(interfaceClass);
  }

  private static void loadComponentRoamingTypes() {
    ExtensionPoint<RoamingTypeExtensionPointBean> point =
        Extensions.getRootArea().getExtensionPoint("com.intellij.ComponentRoamingType");
    final RoamingTypeExtensionPointBean[] componentRoamingTypes = point.getExtensions();

    for (RoamingTypeExtensionPointBean object : componentRoamingTypes) {

      assert object.componentName != null;
      assert object.roamingType != null;

      final RoamingType type = RoamingType.valueOf(object.roamingType);

      assert type != null;

      ComponentRoamingManager.getInstance().setRoamingType(object.componentName, type);
    }
  }

  private void fireBeforeApplicationLoaded() {
    ExtensionPoint<ApplicationLoadListener> point =
        Extensions.getRootArea().getExtensionPoint("com.intellij.ApplicationLoadListener");
    final ApplicationLoadListener[] objects = point.getExtensions();
    for (ApplicationLoadListener object : objects) {
      try {
        object.beforeApplicationLoaded(this);
      } catch (Exception e) {
        LOG.error(e);
      }
    }
  }

  public void dispose() {
    fireApplicationExiting();

    ShutDownTracker.getInstance().ensureStopperThreadsFinished();

    disposeComponents();

    ourThreadExecutorsService.shutdownNow();
    myComponentStore = null;
    super.dispose();
    Disposer.dispose(myLastDisposable); // dispose it last
  }

  private final Object lock = new Object();

  private void makeChangesVisibleToEDT() {
    synchronized (lock) {
      lock.hashCode();
    }
  }

  public boolean runProcessWithProgressSynchronously(
      @NotNull final Runnable process,
      @NotNull String progressTitle,
      boolean canBeCanceled,
      Project project) {
    return runProcessWithProgressSynchronously(
        process, progressTitle, canBeCanceled, project, null);
  }

  public boolean runProcessWithProgressSynchronously(
      @NotNull final Runnable process,
      @NotNull final String progressTitle,
      final boolean canBeCanceled,
      @Nullable final Project project,
      final JComponent parentComponent) {
    return runProcessWithProgressSynchronously(
        process, progressTitle, canBeCanceled, project, parentComponent, null);
  }

  public boolean runProcessWithProgressSynchronously(
      @NotNull final Runnable process,
      @NotNull final String progressTitle,
      final boolean canBeCanceled,
      @Nullable final Project project,
      final JComponent parentComponent,
      final String cancelText) {
    assertIsDispatchThread();

    if (myExceptionalThreadWithReadAccessRunnable != null
        || ApplicationManager.getApplication().isUnitTestMode()
        || ApplicationManager.getApplication().isHeadlessEnvironment()) {
      try {
        ProgressManager.getInstance().runProcess(process, new EmptyProgressIndicator());
      } catch (ProcessCanceledException e) {
        // ok to ignore.
        return false;
      }
      return true;
    }

    final ProgressWindow progress =
        new ProgressWindow(canBeCanceled, false, project, parentComponent, cancelText);
    progress.setTitle(progressTitle);

    try {
      myExceptionalThreadWithReadAccessRunnable = process;
      final boolean[] threadStarted = {false};
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              if (myExceptionalThreadWithReadAccessRunnable != process) {
                LOG.error(
                    "myExceptionalThreadWithReadAccessRunnable != process, process = "
                        + myExceptionalThreadWithReadAccessRunnable);
              }

              executeOnPooledThread(
                  new Runnable() {
                    public void run() {
                      if (myExceptionalThreadWithReadAccessRunnable != process) {
                        LOG.error(
                            "myExceptionalThreadWithReadAccessRunnable != process, process = "
                                + myExceptionalThreadWithReadAccessRunnable);
                      }

                      final boolean old = setExceptionalThreadWithReadAccessFlag(true);
                      LOG.assertTrue(isReadAccessAllowed());
                      try {
                        ProgressManager.getInstance().runProcess(process, progress);
                      } catch (ProcessCanceledException e) {
                        progress.cancel();
                        // ok to ignore.
                      } catch (RuntimeException e) {
                        progress.cancel();
                        throw e;
                      } finally {
                        setExceptionalThreadWithReadAccessFlag(old);
                        makeChangesVisibleToEDT();
                      }
                    }
                  });
              threadStarted[0] = true;
            }
          });

      progress.startBlocking();

      LOG.assertTrue(threadStarted[0]);
      LOG.assertTrue(!progress.isRunning());
    } finally {
      myExceptionalThreadWithReadAccessRunnable = null;
      makeChangesVisibleToEDT();
    }

    return !progress.isCanceled();
  }

  public boolean isInModalProgressThread() {
    if (myExceptionalThreadWithReadAccessRunnable == null || !isExceptionalThreadWithReadAccess()) {
      return false;
    }
    ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
    return progressIndicator.isModal()
        && ((ProgressIndicatorEx) progressIndicator).isModalityEntered();
  }

  public void invokeAndWait(@NotNull Runnable runnable, @NotNull ModalityState modalityState) {
    if (isDispatchThread()) {
      LOG.error("invokeAndWait must not be called from event queue thread");
      runnable.run();
      return;
    }

    if (isExceptionalThreadWithReadAccess()) { // OK if we're in exceptional thread.
      LaterInvocator.invokeAndWait(runnable, modalityState);
      return;
    }

    if (myActionsLock.isReadLockAcquired()) {
      LOG.error("Calling invokeAndWait from read-action leads to possible deadlock.");
    }

    LaterInvocator.invokeAndWait(runnable, modalityState);
  }

  @NotNull
  public ModalityState getCurrentModalityState() {
    Object[] entities = LaterInvocator.getCurrentModalEntities();
    return entities.length > 0 ? new ModalityStateEx(entities) : getNoneModalityState();
  }

  @NotNull
  public ModalityState getModalityStateForComponent(@NotNull Component c) {
    Window window = c instanceof Window ? (Window) c : SwingUtilities.windowForComponent(c);
    if (window == null) return getNoneModalityState(); // ?
    return LaterInvocator.modalityStateForWindow(window);
  }

  @Override
  public ModalityState getAnyModalityState() {
    return ANY;
  }

  @NotNull
  public ModalityState getDefaultModalityState() {
    if (EventQueue.isDispatchThread()) {
      return getCurrentModalityState();
    } else {
      ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
      return progress == null ? getNoneModalityState() : progress.getModalityState();
    }
  }

  @NotNull
  public ModalityState getNoneModalityState() {
    return MODALITY_STATE_NONE;
  }

  public long getStartTime() {
    return myStartTime;
  }

  public long getIdleTime() {
    return IdeEventQueue.getInstance().getIdleTime();
  }

  public void exit() {
    exit(false);
  }

  public void exit(final boolean force) {
    exit(force, true);
  }

  public void exit(final boolean force, final boolean allowListenersToCancel) {
    if (!force && getDefaultModalityState() != ModalityState.NON_MODAL) {
      return;
    }

    Runnable runnable =
        new Runnable() {
          public void run() {
            if (!force && !showConfirmation()) {
              saveAll();
              myExitCode = 0;
              return;
            }

            getMessageBus().syncPublisher(AppLifecycleListener.TOPIC).appClosing();
            myDisposeInProgress = true;

            FileDocumentManager.getInstance().saveAllDocuments();

            saveSettings();

            if (!canExit() && allowListenersToCancel) {
              myExitCode = 0;
              return;
            }

            final boolean success = disposeSelf();
            if (!success || isUnitTestMode()) {
              myExitCode = 0;
              return;
            }

            System.exit(myExitCode);
          }
        };

    if (!isDispatchThread()) {
      invokeLater(runnable, ModalityState.NON_MODAL);
    } else {
      runnable.run();
    }
  }

  private static boolean showConfirmation() {
    final boolean hasUnsafeBgTasks = ProgressManager.getInstance().hasUnsafeProgressIndicator();

    DialogWrapper.DoNotAskOption option =
        new DialogWrapper.DoNotAskOption() {
          @Override
          public boolean isToBeShown() {
            return GeneralSettings.getInstance().isConfirmExit();
          }

          @Override
          public void setToBeShown(boolean value, int exitCode) {
            GeneralSettings.getInstance().setConfirmExit(value);
          }

          @Override
          public boolean canBeHidden() {
            return !hasUnsafeBgTasks;
          }

          @Override
          public boolean shouldSaveOptionsOnCancel() {
            return false;
          }

          @Override
          public String getDoNotShowMessage() {
            return "Do not ask me again";
          }
        };

    if (hasUnsafeBgTasks || option.isToBeShown()) {
      String message =
          ApplicationBundle.message(
              hasUnsafeBgTasks ? "exit.confirm.prompt.tasks" : "exit.confirm.prompt",
              ApplicationNamesInfo.getInstance().getFullProductName());

      if (DialogWrapper.OK_EXIT_CODE
          != Messages.showYesNoDialog(
              message,
              ApplicationBundle.message("exit.confirm.title"),
              ApplicationBundle.message("command.exit"),
              "Cancel",
              Messages.getQuestionIcon(),
              option)) {
        return false;
      }
    }
    return true;
  }

  private boolean canExit() {
    for (ApplicationListener applicationListener : myDispatcher.getListeners()) {
      if (!applicationListener.canExitApplication()) {
        return false;
      }
    }

    ProjectManagerEx projectManager = (ProjectManagerEx) ProjectManager.getInstance();
    Project[] projects = projectManager.getOpenProjects();
    for (Project project : projects) {
      if (!projectManager.canClose(project)) {
        return false;
      }
    }

    return true;
  }

  public void runReadAction(@NotNull final Runnable action) {
    final AccessToken token = acquireReadActionLockImpl(false);

    try {
      action.run();
    } finally {
      token.finish();
    }
  }

  private static final ThreadLocal<Boolean> exceptionalThreadWithReadAccessFlag =
      new ThreadLocal<Boolean>();

  private static boolean isExceptionalThreadWithReadAccess() {
    Boolean flag = exceptionalThreadWithReadAccessFlag.get();
    return flag == Boolean.TRUE;
  }

  public static boolean setExceptionalThreadWithReadAccessFlag(boolean flag) {
    boolean old = isExceptionalThreadWithReadAccess();
    if (flag) {
      exceptionalThreadWithReadAccessFlag.set(Boolean.TRUE);
    } else {
      exceptionalThreadWithReadAccessFlag.remove();
    }
    return old;
  }

  public <T> T runReadAction(@NotNull final Computable<T> computation) {
    final AccessToken token = acquireReadActionLockImpl(false);

    try {
      return computation.compute();
    } finally {
      token.finish();
    }
  }

  public void runWriteAction(@NotNull final Runnable action) {
    final AccessToken token = acquireWriteActionLock(action.getClass());
    try {
      action.run();
    } finally {
      token.finish();
    }
  }

  public <T> T runWriteAction(@NotNull final Computable<T> computation) {
    final AccessToken token = acquireWriteActionLock(computation.getClass());
    try {
      return computation.compute();
    } finally {
      token.finish();
    }
  }

  public boolean hasWriteAction(@Nullable Class<?> actionClass) {
    assertCanRunWriteAction();

    for (int i = myWriteActionsStack.size() - 1; i >= 0; i--) {
      Class action = myWriteActionsStack.get(i);
      if (actionClass == action
          || action != null && ReflectionCache.isAssignable(actionClass, action)) return true;
    }
    return false;
  }

  public void assertReadAccessAllowed() {
    if (myHeadlessMode) return;
    if (!isReadAccessAllowed()) {
      LOG.error(
          "Read access is allowed from event dispatch thread or inside read-action only (see com.intellij.openapi.application.Application.runReadAction())",
          "Current thread: " + describe(Thread.currentThread()),
          "Our dispatch thread:" + describe(ourDispatchThread),
          "SystemEventQueueThread: " + describe(getEventQueueThread()));
    }
  }

  @NonNls
  private static String describe(Thread o) {
    if (o == null) return "null";
    return o.toString() + " " + System.identityHashCode(o);
  }

  @Nullable
  private static Thread getEventQueueThread() {
    EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
    try {
      Method method = EventQueue.class.getDeclaredMethod("getDispatchThread");
      method.setAccessible(true);
      return (Thread) method.invoke(eventQueue);
    } catch (Exception e1) {
      // ok
    }
    return null;
  }

  public boolean isReadAccessAllowed() {
    Thread currentThread = Thread.currentThread();
    return ourDispatchThread == currentThread
        || isExceptionalThreadWithReadAccess()
        || myActionsLock.isReadLockAcquired()
        || myActionsLock.isWriteLockAcquired()
        || isDispatchThread();
  }

  private static void assertCanRunWriteAction() {
    assertIsDispatchThread("Write access is allowed from event dispatch thread only");
  }

  public void assertIsDispatchThread() {
    assertIsDispatchThread("Access is allowed from event dispatch thread only.");
  }

  private static void assertIsDispatchThread(String message) {
    if (ShutDownTracker.isShutdownHookRunning()) return;
    final Thread currentThread = Thread.currentThread();
    if (ourDispatchThread == currentThread) return;

    if (EventQueue.isDispatchThread()) {
      ourDispatchThread = currentThread;
    }
    if (ourDispatchThread == currentThread) return;

    Integer safeCounter = ourEdtSafe.get();
    if (safeCounter != null && safeCounter > 0) return;

    LOG.error(
        message,
        "Current thread: " + describe(Thread.currentThread()),
        "Our dispatch thread:" + describe(ourDispatchThread),
        "SystemEventQueueThread: " + describe(getEventQueueThread()));
  }

  public void runEdtSafeAction(@NotNull Runnable runnable) {
    Integer value = ourEdtSafe.get();
    if (value == null) {
      value = Integer.valueOf(0);
    }

    ourEdtSafe.set(value + 1);

    try {
      runnable.run();
    } finally {
      int newValue = ourEdtSafe.get() - 1;
      ourEdtSafe.set(newValue >= 1 ? newValue : null);
    }
  }

  public void assertIsDispatchThread(@Nullable final JComponent component) {
    if (component == null) return;

    Thread curThread = Thread.currentThread();
    if (ourDispatchThread == curThread) {
      return;
    }

    if (Boolean.TRUE.equals(component.getClientProperty(WAS_EVER_SHOWN))) {
      assertIsDispatchThread();
    } else {
      final JRootPane root = component.getRootPane();
      if (root != null) {
        component.putClientProperty(WAS_EVER_SHOWN, Boolean.TRUE);
        assertIsDispatchThread();
      }
    }
  }

  public void assertTimeConsuming() {
    if (myTestModeFlag || myHeadlessMode || ShutDownTracker.isShutdownHookRunning()) return;
    LOG.assertTrue(
        !isDispatchThread(), "This operation is time consuming and must not be called on EDT");
  }

  public boolean tryRunReadAction(@NotNull Runnable action) {
    /**
     * if we are inside read action, do not try to acquire read lock again since it will deadlock if
     * there is a pending writeAction see {@link
     * com.intellij.util.concurrency.ReentrantWriterPreferenceReadWriteLock#allowReader()}
     */
    boolean mustAcquire = !isReadAccessAllowed();

    if (mustAcquire) {
      LOG.assertTrue(
          myTestModeFlag || !Thread.holdsLock(PsiLock.LOCK),
          "Thread must not hold PsiLock while performing readAction");
      try {
        if (!myActionsLock.readLock().attempt(0)) return false;
      } catch (InterruptedException e) {
        throw new RuntimeInterruptedException(e);
      }
    }

    try {
      action.run();
    } finally {
      if (mustAcquire) {
        myActionsLock.readLock().release();
      }
    }
    return true;
  }

  public boolean tryToApplyActivationState(boolean active, Window window) {
    final Component frame = UIUtil.findUltimateParent(window);

    if (frame instanceof IdeFrame) {
      final IdeFrame ideFrame = (IdeFrame) frame;
      if (isActive() != active) {
        myActive = Boolean.valueOf(active);
        System.setProperty("idea.active", myActive.toString());
        ApplicationActivationListener publisher =
            getMessageBus().syncPublisher(ApplicationActivationListener.TOPIC);
        if (active) {
          publisher.applicationActivated(ideFrame);
        } else {
          publisher.applicationDeactivated(ideFrame);
        }
        return true;
      }
    }

    return false;
  }

  public boolean isActive() {
    if (isUnitTestMode()) return true;

    if (myActive == null) {
      Window active = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
      return active != null;
    }

    return myActive;
  }

  @Override
  public AccessToken acquireReadActionLock() {
    return acquireReadActionLockImpl(true);
  }

  private AccessToken acquireReadActionLockImpl(boolean explicit) {
    /**
     * if we are inside read action, do not try to acquire read lock again since it will deadlock if
     * there is a pending writeAction see {@link
     * com.intellij.util.concurrency.ReentrantWriterPreferenceReadWriteLock#allowReader()}
     */
    if (isReadAccessAllowed()) return AccessToken.EMPTY_ACCESS_TOKEN;

    return new ReadAccessToken(explicit);
  }

  @Override
  public AccessToken acquireWriteActionLock(Class clazz) {
    return new WriteAccessToken(clazz);
  }

  private class WriteAccessToken extends AccessToken {
    private final Class clazz;

    public WriteAccessToken(Class _clazz) {
      clazz = _clazz;
      assertCanRunWriteAction();

      ActivityTracker.getInstance().inc();
      fireBeforeWriteActionStart(_clazz);
      final AtomicBoolean stopped = new AtomicBoolean(false);

      if (ourDumpThreadsOnLongWriteActionWaiting > 0) {
        executeOnPooledThread(
            new Runnable() {
              @Override
              public void run() {
                while (!stopped.get()) {
                  try {
                    Thread.sleep(ourDumpThreadsOnLongWriteActionWaiting);
                    if (!stopped.get()) {
                      PerformanceWatcher.getInstance().dumpThreads(true);
                    }
                  } catch (InterruptedException ignored) {
                  }
                }
              }
            });
      }

      LOG.assertTrue(
          myActionsLock.isWriteLockAcquired(Thread.currentThread())
              || !Thread.holdsLock(PsiLock.LOCK),
          "Thread must not hold PsiLock while performing writeAction");
      try {
        myActionsLock.writeLock().acquire();
        acquired();
      } catch (InterruptedException e) {
        throw new RuntimeInterruptedException(e);
      }
      stopped.set(true);

      myWriteActionsStack.push(_clazz);

      fireWriteActionStarted(_clazz);
    }

    @Override
    public void finish() {
      try {
        fireWriteActionFinished(clazz);

        myWriteActionsStack.pop();
      } finally {
        myActionsLock.writeLock().release();
        released();
      }
    }
  }

  private class ReadAccessToken extends AccessToken {
    private final boolean myExplicit;

    ReadAccessToken(boolean explicit) {
      myExplicit = explicit;
      LOG.assertTrue(
          !Thread.holdsLock(PsiLock.LOCK),
          "Thread must not hold PsiLock while performing readAction");
      try {
        myActionsLock.readLock().acquire();
        if (myExplicit) acquired();
      } catch (InterruptedException e) {
        throw new RuntimeInterruptedException(e);
      }
    }

    @Override
    public void finish() {
      myActionsLock.readLock().release();
      if (myExplicit) released();
    }
  }

  public void assertWriteAccessAllowed() {
    LOG.assertTrue(
        isWriteAccessAllowed(),
        "Write access is allowed inside write-action only (see com.intellij.openapi.application.Application.runWriteAction())");
  }

  public boolean isWriteAccessAllowed() {
    return myActionsLock.isWriteLockAcquired(Thread.currentThread());
  }

  public void editorPaintStart() {
    myInEditorPaintCounter++;
  }

  public void editorPaintFinish() {
    myInEditorPaintCounter--;
    LOG.assertTrue(myInEditorPaintCounter >= 0);
  }

  public void addApplicationListener(@NotNull ApplicationListener l) {
    myDispatcher.addListener(l);
  }

  public void addApplicationListener(@NotNull ApplicationListener l, @NotNull Disposable parent) {
    myDispatcher.addListener(l, parent);
  }

  public void removeApplicationListener(@NotNull ApplicationListener l) {
    myDispatcher.removeListener(l);
  }

  private void fireApplicationExiting() {
    myDispatcher.getMulticaster().applicationExiting();
  }

  private void fireBeforeWriteActionStart(Class action) {
    myDispatcher.getMulticaster().beforeWriteActionStart(action);
  }

  private void fireWriteActionStarted(Class action) {
    myDispatcher.getMulticaster().writeActionStarted(action);
  }

  private void fireWriteActionFinished(Class action) {
    myDispatcher.getMulticaster().writeActionFinished(action);
  }

  public void _saveSettings() { // public for testing purposes
    if (mySaveSettingsIsInProgress.compareAndSet(false, true)) {
      try {
        StoreUtil.doSave(getStateStore());
      } catch (final Throwable ex) {
        if (isUnitTestMode()) {
          System.out.println("Saving application settings failed");
          ex.printStackTrace();
        } else {
          LOG.info("Saving application settings failed", ex);
          invokeLater(
              new Runnable() {
                public void run() {
                  if (ex instanceof PluginException) {
                    final PluginException pluginException = (PluginException) ex;
                    PluginManager.disablePlugin(pluginException.getPluginId().getIdString());
                    Messages.showMessageDialog(
                        "The plugin "
                            + pluginException.getPluginId()
                            + " failed to save settings and has been disabled. Please restart "
                            + ApplicationNamesInfo.getInstance().getFullProductName(),
                        CommonBundle.getErrorTitle(),
                        Messages.getErrorIcon());
                  } else {
                    Messages.showMessageDialog(
                        ApplicationBundle.message(
                            "application.save.settings.error", ex.getLocalizedMessage()),
                        CommonBundle.getErrorTitle(),
                        Messages.getErrorIcon());
                  }
                }
              });
        }
      } finally {
        mySaveSettingsIsInProgress.set(false);
      }
    }
  }

  public void saveSettings() {
    if (myDoNotSave) return;
    _saveSettings();
  }

  public void saveAll() {
    if (myDoNotSave) return;

    FileDocumentManager.getInstance().saveAllDocuments();

    Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
    for (Project openProject : openProjects) {
      ProjectEx project = (ProjectEx) openProject;
      project.save();
    }

    saveSettings();
  }

  public void doNotSave() {
    doNotSave(true);
  }

  public void doNotSave(boolean value) {
    myDoNotSave = value;
  }

  public boolean isDoNotSave() {
    return myDoNotSave;
  }

  public <T> T[] getExtensions(final ExtensionPointName<T> extensionPointName) {
    return Extensions.getRootArea().getExtensionPoint(extensionPointName).getExtensions();
  }

  public boolean isDisposeInProgress() {
    return myDisposeInProgress;
  }

  public boolean isRestartCapable() {
    return SystemInfo.isWindows || SystemInfo.isMacOSSnowLeopard || myRestartCode > 0;
  }

  public void restart() {
    if (SystemInfo.isWindows) {
      Win32Restarter.restart();
    } else if (SystemInfo.isMacOSSnowLeopard) {
      MacRestarter.restart();
    } else if (myRestartCode > 0) {
      myExitCode = myRestartCode;
      exit(true);
    } else {
      exit(true);
    }
  }

  public boolean isSaving() {
    if (getStateStore().isSaving()) return true;
    Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
    for (Project openProject : openProjects) {
      ProjectEx project = (ProjectEx) openProject;
      if (project.getStateStore().isSaving()) return true;
    }

    return false;
  }

  @Override
  protected boolean logSlowComponents() {
    return super.logSlowComponents() || ApplicationInfoImpl.getShadowInstance().isEAP();
  }

  @TestOnly
  public void setDisposeInProgress(boolean disposeInProgress) {
    myDisposeInProgress = disposeInProgress;
  }

  @NonNls
  @Override
  public String toString() {
    return "Application"
        + (isDisposed() ? " (Disposed)" : "")
        + (isUnitTestMode() ? " (Unit test)" : "")
        + (isInternal() ? " (Internal)" : "")
        + (isHeadlessEnvironment() ? " (Headless)" : "")
        + (isCommandLine() ? " (Command line)" : "");
  }
}
  public ApplicationImpl(
      boolean isInternal,
      boolean isUnitTestMode,
      boolean isHeadless,
      boolean isCommandLine,
      @NotNull String appName,
      Splash splash) {
    super(null);

    ApplicationManagerEx.setApplication(
        this, myLastDisposable); // reset back to null only when all components already disposed

    getPicoContainer().registerComponentInstance(Application.class, this);

    CommonBundle.assertKeyIsFound = isUnitTestMode;
    AWTExceptionHandler.register(); // do not crash AWT on exceptions
    if ((isInternal || isUnitTestMode)
        && !Comparing.equal("off", System.getProperty("idea.disposer.debug"))) {
      Disposer.setDebugMode(true);
    }
    myStartTime = System.currentTimeMillis();
    mySplash = splash;
    myName = appName;

    PluginsFacade.INSTANCE =
        new PluginsFacade() {
          public IdeaPluginDescriptor getPlugin(PluginId id) {
            return PluginManager.getPlugin(id);
          }

          public IdeaPluginDescriptor[] getPlugins() {
            return PluginManager.getPlugins();
          }
        };

    myIsInternal = isInternal;
    myTestModeFlag = isUnitTestMode;
    myHeadlessMode = isHeadless;
    myCommandLineMode = isCommandLine;

    myDoNotSave = myTestModeFlag || myHeadlessMode;

    loadApplicationComponents();

    if (myTestModeFlag) {
      registerShutdownHook();
    }

    if (!isUnitTestMode && !isHeadless) {
      Disposer.register(this, Disposer.newDisposable(), "ui");

      StartupUtil.addExternalInstanceListener(
          new Consumer<List<String>>() {
            @Override
            public void consume(final List<String> args) {
              invokeLater(
                  new Runnable() {
                    @Override
                    public void run() {
                      final Project project = CommandLineProcessor.processExternalCommandLine(args);
                      final IdeFrame frame;
                      if (project != null) {
                        frame = WindowManager.getInstance().getIdeFrame(project);
                      } else {
                        frame = WindowManager.getInstance().getAllFrames()[0];
                      }
                      ((IdeFrameImpl) frame).requestFocus();
                    }
                  });
            }
          });
    }

    final String s = System.getProperty("jb.restart.code");
    if (s != null) {
      try {
        myRestartCode = Integer.parseInt(s);
      } catch (NumberFormatException ignore) {
      }
    }

    registerFont("/fonts/Inconsolata.ttf");
  }