@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;
  }