public void runPostStartupActivities() {
    if (postStartupActivityPassed()) {
      return;
    }

    final Application app = ApplicationManager.getApplication();

    if (!app.isHeadlessEnvironment()) {
      checkFsSanity();
      checkProjectRoots();
    }

    runActivities(myDumbAwarePostStartupActivities);

    DumbService.getInstance(myProject)
        .runWhenSmart(
            new Runnable() {
              @Override
              public void run() {
                app.assertIsDispatchThread();

                // myDumbAwarePostStartupActivities might be non-empty if new activities were
                // registered during dumb mode
                runActivities(myDumbAwarePostStartupActivities);

                //noinspection SynchronizeOnThis
                synchronized (StartupManagerImpl.this) {
                  if (!myNotDumbAwarePostStartupActivities.isEmpty()) {
                    while (!myNotDumbAwarePostStartupActivities.isEmpty()) {
                      queueSmartModeActivity(myNotDumbAwarePostStartupActivities.remove(0));
                    }

                    // return here later to set myPostStartupActivitiesPassed
                    DumbService.getInstance(myProject).runWhenSmart(this);
                  } else {
                    myPostStartupActivitiesPassed = true;
                  }
                }
              }
            });

    // otherwise will be stored - we must not create config files in tests
    if (!app.isUnitTestMode()) {
      Registry.get("ide.firstStartup").setValue(false);
    }
  }
  @Override
  public boolean openProject(final Project project) {
    if (isLight(project)) {
      throw new AssertionError("must not open light project");
    }
    final Application application = ApplicationManager.getApplication();

    if (!application.isUnitTestMode() && !((ProjectEx) project).getStateStore().checkVersion()) {
      return false;
    }

    synchronized (myOpenProjects) {
      if (myOpenProjects.contains(project)) {
        return false;
      }
      myOpenProjects.add(project);
      cacheOpenProjects();
    }
    fireProjectOpened(project);

    final StartupManagerImpl startupManager =
        (StartupManagerImpl) StartupManager.getInstance(project);
    waitForFileWatcher(project);
    boolean ok =
        myProgressManager.runProcessWithProgressSynchronously(
            new Runnable() {
              @Override
              public void run() {
                startupManager.runStartupActivities();

                // dumb mode should start before post-startup activities
                // only when startCacheUpdate is called from UI thread, we can guarantee that
                // when the method returns, the application has entered dumb mode
                UIUtil.invokeAndWaitIfNeeded(
                    new Runnable() {
                      @Override
                      public void run() {
                        startupManager.startCacheUpdate();
                      }
                    });

                startupManager.runPostStartupActivitiesFromExtensions();

                UIUtil.invokeLaterIfNeeded(
                    new Runnable() {
                      @Override
                      public void run() {
                        startupManager.runPostStartupActivities();
                      }
                    });
              }
            },
            ProjectBundle.message("project.load.progress"),
            true,
            project);

    if (!ok) {
      closeProject(project, false, false, true);
      notifyProjectOpenFailed();
      return false;
    }

    if (!application.isHeadlessEnvironment() && !application.isUnitTestMode()) {
      // should be invoked last
      startupManager.runWhenProjectIsInitialized(
          new Runnable() {
            @Override
            public void run() {
              final TrackingPathMacroSubstitutor macroSubstitutor =
                  ((ProjectEx) project)
                      .getStateStore()
                      .getStateStorageManager()
                      .getMacroSubstitutor();
              if (macroSubstitutor != null) {
                StorageUtil.notifyUnknownMacros(macroSubstitutor, project, null);
              }
            }
          });
    }

    return true;
  }