static boolean shouldSkipPlugin(
      final IdeaPluginDescriptor descriptor, IdeaPluginDescriptor[] loaded) {
    final String idString = descriptor.getPluginId().getIdString();
    if (idString.equals(CORE_PLUGIN_ID)) {
      return false;
    }

    //noinspection HardCodedStringLiteral
    final String pluginId = System.getProperty("idea.load.plugins.id");
    if (pluginId == null) {
      if (descriptor instanceof IdeaPluginDescriptorImpl && !descriptor.isEnabled()) return true;

      if (!shouldLoadPlugins()) return true;
    }
    final List<String> pluginIds = pluginId == null ? null : StringUtil.split(pluginId, ",");

    final boolean checkModuleDependencies =
        !ourAvailableModules.isEmpty() && !ourAvailableModules.contains("com.intellij.modules.all");
    if (checkModuleDependencies && !hasModuleDependencies(descriptor)) {
      return true;
    }

    boolean shouldLoad;
    //noinspection HardCodedStringLiteral
    final String loadPluginCategory = System.getProperty("idea.load.plugins.category");
    if (loadPluginCategory != null) {
      shouldLoad = loadPluginCategory.equals(descriptor.getCategory());
    } else {
      if (pluginIds != null) {
        shouldLoad = pluginIds.contains(idString);
        if (!shouldLoad) {
          Map<PluginId, IdeaPluginDescriptor> map = new HashMap<PluginId, IdeaPluginDescriptor>();
          for (final IdeaPluginDescriptor pluginDescriptor : loaded) {
            map.put(pluginDescriptor.getPluginId(), pluginDescriptor);
          }
          addModulesAsDependents(map);
          final IdeaPluginDescriptor descriptorFromProperty = map.get(PluginId.getId(pluginId));
          shouldLoad =
              descriptorFromProperty != null
                  && isDependent(
                      descriptorFromProperty,
                      descriptor.getPluginId(),
                      map,
                      checkModuleDependencies);
        }
      } else {
        shouldLoad = !getDisabledPlugins().contains(idString);
      }
      if (shouldLoad && descriptor instanceof IdeaPluginDescriptorImpl) {
        if (isIncompatible(descriptor)) return true;
      }
    }

    return !shouldLoad;
  }
  @NotNull
  private static PsiClass[] resolveClassReferenceList(
      @NotNull PsiClassType[] listOfTypes,
      @NotNull PsiManager manager,
      @NotNull GlobalSearchScope resolveScope,
      boolean includeObject) {
    PsiClass objectClass =
        JavaPsiFacade.getInstance(manager.getProject())
            .findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);
    if (objectClass == null) includeObject = false;
    if (listOfTypes.length == 0) {
      if (includeObject) return new PsiClass[] {objectClass};
      return PsiClass.EMPTY_ARRAY;
    }

    int referenceCount = listOfTypes.length;
    if (includeObject) referenceCount++;

    PsiClass[] resolved = new PsiClass[referenceCount];
    int resolvedCount = 0;

    if (includeObject) resolved[resolvedCount++] = objectClass;
    for (PsiClassType reference : listOfTypes) {
      PsiClass refResolved = reference.resolve();
      if (refResolved != null) resolved[resolvedCount++] = refResolved;
    }

    if (resolvedCount < referenceCount) {
      PsiClass[] shorter = new PsiClass[resolvedCount];
      System.arraycopy(resolved, 0, shorter, 0, resolvedCount);
      resolved = shorter;
    }

    return resolved;
  }
 public static void initPlugins(@Nullable StartupProgress progress) {
   long start = System.currentTimeMillis();
   try {
     initializePlugins(progress);
   } catch (RuntimeException e) {
     getLogger().error(e);
     throw e;
   }
   getLogger()
       .info(
           ourPlugins.length
               + " plugins initialized in "
               + (System.currentTimeMillis() - start)
               + " ms");
   logPlugins();
   ClassUtilCore.clearJarURLCache();
 }
  private void doPostponedFormattingInner(final FileViewProvider key) {

    final List<ASTNode> astNodes = myReformatElements.remove(key);
    final Document document = key.getDocument();
    // Sort ranges by end offsets so that we won't need any offset adjustment after reformat or
    // reindent
    if (document == null) return;

    final VirtualFile virtualFile = key.getVirtualFile();
    if (!virtualFile.isValid()) return;

    final TreeSet<PostprocessFormattingTask> postProcessTasks =
        new TreeSet<PostprocessFormattingTask>();
    Collection<Disposable> toDispose = ContainerUtilRt.newArrayList();
    try {
      // process all roots in viewProvider to find marked for reformat before elements and create
      // appropriate range markers
      handleReformatMarkers(key, postProcessTasks);
      toDispose.addAll(postProcessTasks);

      // then we create ranges by changed nodes. One per node. There ranges can intersect. Ranges
      // are sorted by end offset.
      if (astNodes != null) createActionsMap(astNodes, key, postProcessTasks);

      if ("true".equals(System.getProperty("check.psi.is.valid"))
          && ApplicationManager.getApplication().isUnitTestMode()) {
        checkPsiIsCorrect(key);
      }

      while (!postProcessTasks.isEmpty()) {
        // now we have to normalize actions so that they not intersect and ordered in most
        // appropriate way
        // (free reformatting -> reindent -> formatting under reindent)
        final List<PostponedAction> normalizedActions =
            normalizeAndReorderPostponedActions(postProcessTasks, document);
        toDispose.addAll(normalizedActions);

        // only in following loop real changes in document are made
        for (final PostponedAction normalizedAction : normalizedActions) {
          CodeStyleSettings settings =
              CodeStyleSettingsManager.getSettings(myPsiManager.getProject());
          boolean old = settings.ENABLE_JAVADOC_FORMATTING;
          settings.ENABLE_JAVADOC_FORMATTING = false;
          try {
            normalizedAction.execute(key);
          } finally {
            settings.ENABLE_JAVADOC_FORMATTING = old;
          }
        }
      }
    } finally {
      for (Disposable disposable : toDispose) {
        //noinspection SSBasedInspection
        disposable.dispose();
      }
    }
  }
 @NotNull
 public static List<String> getDisabledPlugins() {
   if (ourDisabledPlugins == null) {
     ourDisabledPlugins = new ArrayList<String>();
     if (System.getProperty("idea.ignore.disabled.plugins") == null && !isUnitTestMode()) {
       loadDisabledPlugins(PathManager.getConfigPath(), ourDisabledPlugins);
     }
   }
   return ourDisabledPlugins;
 }
  @NotNull
  private static PsiClass[] getSupersInner(@NotNull PsiClass psiClass) {
    PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes();
    PsiClassType[] implementsListTypes = psiClass.getImplementsListTypes();

    if (psiClass.isInterface()) {
      return resolveClassReferenceList(
          extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), true);
    }

    if (psiClass instanceof PsiAnonymousClass) {
      PsiAnonymousClass psiAnonymousClass = (PsiAnonymousClass) psiClass;
      PsiClassType baseClassReference = psiAnonymousClass.getBaseClassType();
      PsiClass baseClass = baseClassReference.resolve();
      if (baseClass != null) {
        if (baseClass.isInterface()) {
          PsiClass objectClass =
              JavaPsiFacade.getInstance(psiClass.getProject())
                  .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope());
          return objectClass != null
              ? new PsiClass[] {objectClass, baseClass}
              : new PsiClass[] {baseClass};
        }
        return new PsiClass[] {baseClass};
      }

      PsiClass objectClass =
          JavaPsiFacade.getInstance(psiClass.getProject())
              .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope());
      return objectClass != null ? new PsiClass[] {objectClass} : PsiClass.EMPTY_ARRAY;
    }
    if (psiClass instanceof PsiTypeParameter) {
      if (extendsListTypes.length == 0) {
        final PsiClass objectClass =
            JavaPsiFacade.getInstance(psiClass.getProject())
                .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope());
        return objectClass != null ? new PsiClass[] {objectClass} : PsiClass.EMPTY_ARRAY;
      }
      return resolveClassReferenceList(
          extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false);
    }

    PsiClass[] interfaces =
        resolveClassReferenceList(
            implementsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false);

    PsiClass superClass = getSuperClass(psiClass);
    if (superClass == null) return interfaces;
    PsiClass[] types = new PsiClass[interfaces.length + 1];
    types[0] = superClass;
    System.arraycopy(interfaces, 0, types, 1, interfaces.length);

    return types;
  }
 static boolean shouldLoadPlugins() {
   try {
     // no plugins during bootstrap
     Class.forName("com.intellij.openapi.extensions.Extensions");
   } catch (ClassNotFoundException e) {
     return false;
   }
   //noinspection HardCodedStringLiteral
   final String loadPlugins = System.getProperty("idea.load.plugins");
   return loadPlugins == null || Boolean.TRUE.toString().equals(loadPlugins);
 }
 static BuildNumber getBuildNumber() {
   if (ourBuildNumber == null) {
     ourBuildNumber = BuildNumber.fromString(System.getProperty("idea.plugins.compatible.build"));
     if (ourBuildNumber == null) {
       ourBuildNumber = BUILD_NUMBER == null ? null : BuildNumber.fromString(BUILD_NUMBER);
       if (ourBuildNumber == null) {
         ourBuildNumber = BuildNumber.fallback();
       }
     }
   }
   return ourBuildNumber;
 }
  @Override
  @Nullable
  public Project newProject(
      final String projectName,
      @NotNull String filePath,
      boolean useDefaultProjectSettings,
      boolean isDummy) {
    filePath = toCanonicalName(filePath);

    //noinspection ConstantConditions
    if (LOG_PROJECT_LEAKAGE_IN_TESTS && ApplicationManager.getApplication().isUnitTestMode()) {
      for (int i = 0; i < 42; i++) {
        if (myProjects.size() < MAX_LEAKY_PROJECTS) break;
        System.gc();
        TimeoutUtil.sleep(100);
        System.gc();
      }

      if (myProjects.size() >= MAX_LEAKY_PROJECTS) {
        List<Project> copy = new ArrayList<Project>(myProjects.keySet());
        myProjects.clear();
        throw new TooManyProjectLeakedException(copy);
      }
    }

    ProjectImpl project =
        createProject(
            projectName, filePath, false, ApplicationManager.getApplication().isUnitTestMode());
    try {
      initProject(project, useDefaultProjectSettings ? (ProjectImpl) getDefaultProject() : null);
      if (LOG_PROJECT_LEAKAGE_IN_TESTS) {
        myProjects.put(project, null);
      }
      return project;
    } catch (final Exception e) {
      LOG.info(e);
      Messages.showErrorDialog(message(e), ProjectBundle.message("project.load.default.error"));
    }
    return null;
  }
  static void loadDescriptorsFromProperty(final List<IdeaPluginDescriptorImpl> result) {
    final String pathProperty = System.getProperty(PROPERTY_PLUGIN_PATH);
    if (pathProperty == null) return;

    for (StringTokenizer t = new StringTokenizer(pathProperty, File.pathSeparator);
        t.hasMoreTokens(); ) {
      String s = t.nextToken();
      final IdeaPluginDescriptorImpl ideaPluginDescriptor = loadDescriptor(new File(s), PLUGIN_XML);
      if (ideaPluginDescriptor != null) {
        result.add(ideaPluginDescriptor);
      }
    }
  }
  static {
    // Radar #5755208: Command line Java applications need a way to launch without a Dock icon.
    System.setProperty("apple.awt.UIElement", "true");

    try {
      CodeInsightSettings defaultSettings = new CodeInsightSettings();
      Element oldS = new Element("temp");
      defaultSettings.writeExternal(oldS);
      DEFAULT_SETTINGS_EXTERNALIZED = JDOMUtil.writeElement(oldS, "\n");
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  @NotNull
  public static PsiClassType[] getSuperTypes(@NotNull PsiClass psiClass) {
    if (psiClass instanceof PsiAnonymousClass) {
      PsiClassType baseClassType = ((PsiAnonymousClass) psiClass).getBaseClassType();
      PsiClass baseClass = baseClassType.resolve();
      if (baseClass == null || !baseClass.isInterface()) {
        return new PsiClassType[] {baseClassType};
      } else {
        PsiClassType objectType =
            PsiType.getJavaLangObject(psiClass.getManager(), psiClass.getResolveScope());
        return new PsiClassType[] {objectType, baseClassType};
      }
    }

    PsiClassType[] extendsTypes = psiClass.getExtendsListTypes();
    PsiClassType[] implementsTypes = psiClass.getImplementsListTypes();
    boolean hasExtends = extendsTypes.length != 0;
    int extendsListLength = extendsTypes.length + (hasExtends ? 0 : 1);
    PsiClassType[] result = new PsiClassType[extendsListLength + implementsTypes.length];

    System.arraycopy(extendsTypes, 0, result, 0, extendsTypes.length);
    if (!hasExtends) {
      if (CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) {
        return PsiClassType.EMPTY_ARRAY;
      }
      PsiManager manager = psiClass.getManager();
      PsiClassType objectType = PsiType.getJavaLangObject(manager, psiClass.getResolveScope());
      result[0] = objectType;
    }
    System.arraycopy(implementsTypes, 0, result, extendsListLength, implementsTypes.length);
    for (int i = 0; i < result.length; i++) {
      PsiClassType type = result[i];
      result[i] = (PsiClassType) PsiUtil.captureToplevelWildcards(type, psiClass);
    }
    return result;
  }
 @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);
 }
示例#14
0
  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", Boolean.valueOf(myActive).toString());
        if (active) {
          myDispatcher.getMulticaster().applicationActivated(ideFrame);
        } else {
          myDispatcher.getMulticaster().applicationDeactivated(ideFrame);
        }
        return true;
      }
    }

    return false;
  }
  static void loadDescriptorsFromClassPath(
      @NotNull List<IdeaPluginDescriptorImpl> result, @Nullable StartupProgress progress) {
    Collection<URL> urls = getClassLoaderUrls();
    String platformPrefix = System.getProperty(PlatformUtilsCore.PLATFORM_PREFIX_KEY);
    int i = 0;
    for (URL url : urls) {
      i++;
      if ("file".equals(url.getProtocol())) {
        File file = new File(decodeUrl(url.getFile()));

        IdeaPluginDescriptorImpl platformPluginDescriptor = null;
        if (platformPrefix != null) {
          platformPluginDescriptor = loadDescriptor(file, platformPrefix + "Plugin.xml");
          if (platformPluginDescriptor != null && !result.contains(platformPluginDescriptor)) {
            platformPluginDescriptor.setUseCoreClassLoader(true);
            result.add(platformPluginDescriptor);
          }
        }

        IdeaPluginDescriptorImpl pluginDescriptor = loadDescriptor(file, PLUGIN_XML);
        if (platformPrefix != null
            && pluginDescriptor != null
            && pluginDescriptor.getName().equals(SPECIAL_IDEA_PLUGIN)) {
          continue;
        }
        if (pluginDescriptor != null && !result.contains(pluginDescriptor)) {
          if (platformPluginDescriptor != null) {
            // if we found a regular plugin.xml in the same .jar/root as a platform-prefixed
            // descriptor, use the core loader for it too
            pluginDescriptor.setUseCoreClassLoader(true);
          }
          result.add(pluginDescriptor);
          if (progress != null) {
            progress.showProgress(
                "Plugin loaded: " + pluginDescriptor.getName(),
                PLUGINS_PROGRESS_MAX_VALUE * ((float) i / urls.size()));
          }
        }
      }
    }
  }
  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;
  }
 @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);
   ContentUtilEx.addTabbedContent(
       contentManager,
       updateInfoTree,
       "Update Info",
       DateFormatUtil.formatDateTime(System.currentTimeMillis()),
       true,
       updateInfoTree);
   ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.VCS).activate(null);
   updateInfoTree.expandRootChildren();
   return updateInfoTree;
 }
示例#18
0
  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 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");
  }
  static void initializePlugins(@Nullable StartupProgress progress) {
    configureExtensions();

    final IdeaPluginDescriptorImpl[] pluginDescriptors = loadDescriptors(progress);

    final Class callerClass = ReflectionUtil.findCallerClass(1);
    assert callerClass != null;
    final ClassLoader parentLoader = callerClass.getClassLoader();

    final List<IdeaPluginDescriptorImpl> result = new ArrayList<IdeaPluginDescriptorImpl>();
    final HashMap<String, String> disabledPluginNames = new HashMap<String, String>();
    for (IdeaPluginDescriptorImpl descriptor : pluginDescriptors) {
      if (descriptor.getPluginId().getIdString().equals(CORE_PLUGIN_ID)) {
        final List<String> modules = descriptor.getModules();
        if (modules != null) {
          ourAvailableModules.addAll(modules);
        }
      }

      if (!shouldSkipPlugin(descriptor, pluginDescriptors)) {
        result.add(descriptor);
      } else {
        descriptor.setEnabled(false);
        disabledPluginNames.put(descriptor.getPluginId().getIdString(), descriptor.getName());
        initClassLoader(parentLoader, descriptor);
      }
    }

    prepareLoadingPluginsErrorMessage(filterBadPlugins(result, disabledPluginNames));

    final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap =
        new HashMap<PluginId, IdeaPluginDescriptorImpl>();
    for (final IdeaPluginDescriptorImpl descriptor : result) {
      idToDescriptorMap.put(descriptor.getPluginId(), descriptor);
    }

    final IdeaPluginDescriptor corePluginDescriptor =
        idToDescriptorMap.get(PluginId.getId(CORE_PLUGIN_ID));
    assert corePluginDescriptor != null
        : CORE_PLUGIN_ID
            + " not found; platform prefix is "
            + System.getProperty(PlatformUtilsCore.PLATFORM_PREFIX_KEY);
    for (IdeaPluginDescriptorImpl descriptor : result) {
      if (descriptor != corePluginDescriptor) {
        descriptor.insertDependency(corePluginDescriptor);
      }
    }

    mergeOptionalConfigs(idToDescriptorMap);

    // sort descriptors according to plugin dependencies
    Collections.sort(result, getPluginDescriptorComparator(idToDescriptorMap));

    for (int i = 0; i < result.size(); i++) {
      ourId2Index.put(result.get(i).getPluginId(), i);
    }

    int i = 0;
    for (final IdeaPluginDescriptorImpl pluginDescriptor : result) {
      if (pluginDescriptor.getPluginId().getIdString().equals(CORE_PLUGIN_ID)
          || pluginDescriptor.isUseCoreClassLoader()) {
        pluginDescriptor.setLoader(parentLoader, true);
      } else {
        final List<File> classPath = pluginDescriptor.getClassPath();
        final PluginId[] dependentPluginIds = pluginDescriptor.getDependentPluginIds();
        final ClassLoader[] parentLoaders = getParentLoaders(idToDescriptorMap, dependentPluginIds);

        final ClassLoader pluginClassLoader =
            createPluginClassLoader(
                classPath.toArray(new File[classPath.size()]),
                parentLoaders.length > 0 ? parentLoaders : new ClassLoader[] {parentLoader},
                pluginDescriptor);
        pluginDescriptor.setLoader(pluginClassLoader, true);
      }

      pluginDescriptor.registerExtensions();
      if (progress != null) {
        progress.showProgress(
            "", PLUGINS_PROGRESS_MAX_VALUE + (i++ / (float) result.size()) * 0.35f);
      }
    }

    ourPlugins = pluginDescriptors;
  }
示例#21
0
 static {
   System.setProperty("jbdt.test.fixture", "com.intellij.designer.dt.IJTestFixture");
 }
示例#22
0
@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 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<Runnable> myWriteActionsStack =
      new Stack<Runnable>(); // accessed from EDT only, no need to sync

  private volatile Runnable myExceptionalThreadWithReadAccessRunnable;

  private int myInEditorPaintCounter = 0;
  private long myStartTime = 0;
  private boolean myDoNotSave = false;
  private volatile boolean myDisposeInProgress = false;

  private int myRestartCode = 0;
  private volatile int myExitCode = 0;

  private final AtomicBoolean mySaveSettingsIsInProgress = new AtomicBoolean(false);

  @SuppressWarnings({"UseOfArchaicSystemPropertyAccessors"})
  private static final int ourDumpThreadsOnLongWriteActionWaiting =
      Integer.getInteger(System.getProperty("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>();

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

  @Override
  @NotNull
  public synchronized IApplicationStore getStateStore() {
    return (IApplicationStore) super.getStateStore();
  }

  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) {
      }
    }
  }

  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;
                }
                try {
                  SwingUtilities.invokeAndWait(
                      new Runnable() {
                        public void run() {
                          ApplicationManagerEx.setApplication(ApplicationImpl.this);
                          try {
                            saveAll();
                          } finally {
                            disposeSelf();
                          }
                        }
                      });
                } catch (InterruptedException e) {
                  LOG.error(e);
                } catch (InvocationTargetException e) {
                  LOG.error(e);
                }
              }
            });
  }

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

  @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);
    } else 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() {
    final IdeaPluginDescriptor[] plugins = PluginManager.getPlugins();
    for (IdeaPluginDescriptor plugin : plugins) {
      if (PluginManager.shouldSkipPlugin(plugin)) continue;
      loadComponentsConfiguration(plugin.getAppComponents(), plugin, false);
    }
  }

  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 IdeaPluginDescriptor getPlugin(PluginId id) {
    return PluginsFacade.INSTANCE.getPlugin(id);
  }

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

  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();

    try {
      getStateStore().load();
    } catch (StateStorage.StateStorageException e) {
      throw new IOException(e.getMessage());
    }
  }

  @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) {
      object.beforeApplicationLoaded(this);
    }
  }

  public void dispose() {
    fireApplicationExiting();
    disposeComponents();

    ourThreadExecutorsService.shutdownNow();
    super.dispose();
  }

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

  @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) {
    if (!force && getDefaultModalityState() != ModalityState.NON_MODAL) {
      return;
    }

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

            getMessageBus().syncPublisher(AppLifecycleListener.TOPIC).appClosing();

            FileDocumentManager.getInstance().saveAllDocuments();

            saveSettings();

            if (!canExit()) {
              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();
    final ConfirmExitDialog confirmExitDialog = new ConfirmExitDialog(hasUnsafeBgTasks);
    if (confirmExitDialog.isToBeShown()) {
      confirmExitDialog.show();
      if (!confirmExitDialog.isOK()) {
        return false;
      }
    } else {
      confirmExitDialog.close(DialogWrapper.OK_EXIT_CODE);
    }
    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) {
    /**
     * 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()) {
      action.run();
      return;
    }

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

    try {
      action.run();
    } finally {
      myActionsLock.readLock().release();
    }
  }

  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 Ref<T> ref = Ref.create(null);
    runReadAction(
        new Runnable() {
          public void run() {
            ref.set(computation.compute());
          }
        });
    return ref.get();
  }

  public void runWriteAction(@NotNull final Runnable action) {
    assertCanRunWriteAction();

    ActivityTracker.getInstance().inc();
    fireBeforeWriteActionStart(action);
    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();
    } catch (InterruptedException e) {
      throw new RuntimeInterruptedException(e);
    }
    stopped.set(true);

    try {
      myWriteActionsStack.push(action);

      fireWriteActionStarted(action);

      action.run();
    } finally {
      try {
        fireWriteActionFinished(action);

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

  public <T> T runWriteAction(@NotNull final Computable<T> computation) {
    final Ref<T> ref = Ref.create(null);
    runWriteAction(
        new Runnable() {
          public void run() {
            ref.set(computation.compute());
          }
        });
    return ref.get();
  }

  public <T> T getCurrentWriteAction(@Nullable Class<T> actionClass) {
    assertCanRunWriteAction();

    for (int i = myWriteActionsStack.size() - 1; i >= 0; i--) {
      Runnable action = myWriteActionsStack.get(i);
      if (actionClass == null || ReflectionCache.isAssignable(actionClass, action.getClass()))
        return (T) action;
    }
    return null;
  }

  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();
  }

  public void assertReadAccessToDocumentsAllowed() {
    /* TODO
    Thread currentThread = Thread.currentThread();
    if (ourDispatchThread != currentThread) {
      if (myExceptionalThreadWithReadAccess == currentThread) return;
      if (myActionsLock.isReadLockAcquired(currentThread)) return;
      if (myActionsLock.isWriteLockAcquired(currentThread)) return;
      if (isDispatchThread(currentThread)) return;
      LOG.error(
        "Read access is allowed from event dispatch thread or inside read-action only (see com.intellij.openapi.application.Application.runReadAction())");
    }
    */
  }

  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", Boolean.valueOf(myActive).toString());
        if (active) {
          myDispatcher.getMulticaster().applicationActivated(ideFrame);
        } else {
          myDispatcher.getMulticaster().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;
  }

  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(Runnable action) {
    myDispatcher.getMulticaster().beforeWriteActionStart(action);
  }

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

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

  public void _saveSettings() { // public for testing purposes
    if (mySaveSettingsIsInProgress.compareAndSet(false, true)) {
      try {
        doSave();
      } 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 && !isUnitTestMode() && !isHeadlessEnvironment()) {
      _saveSettings();
    }
  }

  public void saveAll() {
    if (myDoNotSave || isUnitTestMode() || isHeadlessEnvironment()) return;

    FileDocumentManager.getInstance().saveAllDocuments();

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

    saveSettings();
  }

  public void doNotSave() {
    myDoNotSave = true;
  }

  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
  public String toString() {
    return "Application";
  }
}
示例#23
0
 @NonNls
 private static String describe(Thread o) {
   if (o == null) return "null";
   return o.toString() + " " + System.identityHashCode(o);
 }
/** @author peter */
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public abstract class UsefulTestCase extends TestCase {
  public static final boolean IS_UNDER_TEAMCITY = System.getenv("TEAMCITY_VERSION") != null;

  public static final String IDEA_MARKER_CLASS =
      "com.intellij.openapi.components.impl.stores.IdeaProjectStoreImpl";
  public static final String TEMP_DIR_MARKER = "unitTest_";

  protected static boolean OVERWRITE_TESTDATA = false;

  private static final String DEFAULT_SETTINGS_EXTERNALIZED;
  private static final Random RNG = new SecureRandom();
  private static final String ORIGINAL_TEMP_DIR = FileUtil.getTempDirectory();

  protected final Disposable myTestRootDisposable =
      new Disposable() {
        @Override
        public void dispose() {}

        @Override
        public String toString() {
          String testName = getTestName(false);
          return UsefulTestCase.this.getClass()
              + (StringUtil.isEmpty(testName) ? "" : ".test" + testName);
        }
      };

  protected static String ourPathToKeep = null;

  private CodeStyleSettings myOldCodeStyleSettings;
  private String myTempDir;

  protected static final Key<String> CREATION_PLACE = Key.create("CREATION_PLACE");

  static {
    // Radar #5755208: Command line Java applications need a way to launch without a Dock icon.
    System.setProperty("apple.awt.UIElement", "true");

    try {
      CodeInsightSettings defaultSettings = new CodeInsightSettings();
      Element oldS = new Element("temp");
      defaultSettings.writeExternal(oldS);
      DEFAULT_SETTINGS_EXTERNALIZED = JDOMUtil.writeElement(oldS, "\n");
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  protected boolean shouldContainTempFiles() {
    return true;
  }

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    if (shouldContainTempFiles()) {
      String testName = getTestName(true);
      if (StringUtil.isEmptyOrSpaces(testName)) testName = "";
      testName = new File(testName).getName(); // in case the test name contains file separators
      myTempDir =
          FileUtil.toSystemDependentName(
              ORIGINAL_TEMP_DIR + "/" + TEMP_DIR_MARKER + testName + "_" + RNG.nextInt(1000));
      FileUtil.resetCanonicalTempPathCache(myTempDir);
    }
    //noinspection AssignmentToStaticFieldFromInstanceMethod
    DocumentImpl.CHECK_DOCUMENT_CONSISTENCY = !isPerformanceTest();
  }

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

  private static final Set<String> DELETE_ON_EXIT_HOOK_DOT_FILES;
  private static final Class DELETE_ON_EXIT_HOOK_CLASS;

  static {
    Class<?> aClass = null;
    Set<String> files = null;
    try {
      aClass = Class.forName("java.io.DeleteOnExitHook");
      files = ReflectionUtil.getField(aClass, null, Set.class, "files");
    } catch (Exception ignored) {
    }
    DELETE_ON_EXIT_HOOK_CLASS = aClass;
    DELETE_ON_EXIT_HOOK_DOT_FILES = files;
  }

  public static void cleanupDeleteOnExitHookList()
      throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
    // try to reduce file set retained by java.io.DeleteOnExitHook
    List<String> list;
    synchronized (DELETE_ON_EXIT_HOOK_CLASS) {
      if (DELETE_ON_EXIT_HOOK_DOT_FILES.isEmpty()) return;
      list = new ArrayList<String>(DELETE_ON_EXIT_HOOK_DOT_FILES);
    }
    for (int i = list.size() - 1; i >= 0; i--) {
      String path = list.get(i);
      if (FileSystemUtil.getAttributes(path) == null || new File(path).delete()) {
        synchronized (DELETE_ON_EXIT_HOOK_CLASS) {
          DELETE_ON_EXIT_HOOK_DOT_FILES.remove(path);
        }
      }
    }
  }

  private static void cleanupSwingDataStructures() throws Exception {
    Class<?> aClass = Class.forName("javax.swing.KeyboardManager");

    Method get = aClass.getMethod("getCurrentManager");
    get.setAccessible(true);
    Object manager = get.invoke(null);
    {
      Field mapF = aClass.getDeclaredField("componentKeyStrokeMap");
      mapF.setAccessible(true);
      Object map = mapF.get(manager);
      ((Map) map).clear();
    }
    {
      Field mapF = aClass.getDeclaredField("containerMap");
      mapF.setAccessible(true);
      Object map = mapF.get(manager);
      ((Map) map).clear();
    }
  }

  protected CompositeException checkForSettingsDamage() throws Exception {
    Application app = ApplicationManager.getApplication();
    if (isPerformanceTest() || app == null || app instanceof MockApplication) {
      return new CompositeException();
    }

    CodeStyleSettings oldCodeStyleSettings = myOldCodeStyleSettings;
    myOldCodeStyleSettings = null;

    return doCheckForSettingsDamage(oldCodeStyleSettings, getCurrentCodeStyleSettings());
  }

  public static CompositeException doCheckForSettingsDamage(
      @NotNull CodeStyleSettings oldCodeStyleSettings,
      @NotNull CodeStyleSettings currentCodeStyleSettings)
      throws Exception {
    CompositeException result = new CompositeException();
    final CodeInsightSettings settings = CodeInsightSettings.getInstance();
    try {
      Element newS = new Element("temp");
      settings.writeExternal(newS);
      Assert.assertEquals(
          "Code insight settings damaged",
          DEFAULT_SETTINGS_EXTERNALIZED,
          JDOMUtil.writeElement(newS, "\n"));
    } catch (AssertionError error) {
      CodeInsightSettings clean = new CodeInsightSettings();
      Element temp = new Element("temp");
      clean.writeExternal(temp);
      settings.loadState(temp);
      result.add(error);
    }

    currentCodeStyleSettings.getIndentOptions(StdFileTypes.JAVA);
    try {
      checkSettingsEqual(
          oldCodeStyleSettings, currentCodeStyleSettings, "Code style settings damaged");
    } catch (AssertionError e) {
      result.add(e);
    } finally {
      currentCodeStyleSettings.clearCodeStyleSettings();
    }

    try {
      InplaceRefactoring.checkCleared();
    } catch (AssertionError e) {
      result.add(e);
    }
    try {
      StartMarkAction.checkCleared();
    } catch (AssertionError e) {
      result.add(e);
    }

    return result;
  }

  protected void storeSettings() {
    if (!isPerformanceTest() && ApplicationManager.getApplication() != null) {
      myOldCodeStyleSettings = getCurrentCodeStyleSettings().clone();
      myOldCodeStyleSettings.getIndentOptions(StdFileTypes.JAVA);
    }
  }

  protected CodeStyleSettings getCurrentCodeStyleSettings() {
    if (CodeStyleSchemes.getInstance().getCurrentScheme() == null) return new CodeStyleSettings();
    return CodeStyleSettingsManager.getInstance().getCurrentSettings();
  }

  public Disposable getTestRootDisposable() {
    return myTestRootDisposable;
  }

  @Override
  protected void runTest() throws Throwable {
    final Throwable[] throwables = new Throwable[1];

    Runnable runnable =
        new Runnable() {
          @Override
          public void run() {
            try {
              UsefulTestCase.super.runTest();
            } catch (InvocationTargetException e) {
              e.fillInStackTrace();
              throwables[0] = e.getTargetException();
            } catch (IllegalAccessException e) {
              e.fillInStackTrace();
              throwables[0] = e;
            } catch (Throwable e) {
              throwables[0] = e;
            }
          }
        };

    invokeTestRunnable(runnable);

    if (throwables[0] != null) {
      throw throwables[0];
    }
  }

  protected boolean shouldRunTest() {
    return PlatformTestUtil.canRunTest(getClass());
  }

  public static void edt(Runnable r) {
    UIUtil.invokeAndWaitIfNeeded(r);
  }

  protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
    UIUtil.invokeAndWaitIfNeeded(runnable);
    // runnable.run();
  }

  protected void defaultRunBare() throws Throwable {
    super.runBare();
  }

  @Override
  public void runBare() throws Throwable {
    if (!shouldRunTest()) return;

    if (runInDispatchThread()) {
      final Throwable[] exception = {null};
      UIUtil.invokeAndWaitIfNeeded(
          new Runnable() {
            @Override
            public void run() {
              try {
                defaultRunBare();
              } catch (Throwable tearingDown) {
                if (exception[0] == null) exception[0] = tearingDown;
              }
            }
          });
      if (exception[0] != null) throw exception[0];
    } else {
      defaultRunBare();
    }
  }

  protected boolean runInDispatchThread() {
    return true;
  }

  @NonNls
  public static String toString(Iterable<?> collection) {
    if (!collection.iterator().hasNext()) {
      return "<empty>";
    }

    final StringBuilder builder = new StringBuilder();
    for (final Object o : collection) {
      if (o instanceof THashSet) {
        builder.append(new TreeSet<Object>((THashSet) o));
      } else {
        builder.append(o);
      }
      builder.append("\n");
    }
    return builder.toString();
  }

  public static <T> void assertOrderedEquals(T[] actual, T... expected) {
    assertOrderedEquals(Arrays.asList(actual), expected);
  }

  public static <T> void assertOrderedEquals(Iterable<T> actual, T... expected) {
    assertOrderedEquals(null, actual, expected);
  }

  public static void assertOrderedEquals(@NotNull byte[] actual, @NotNull byte[] expected) {
    assertEquals(actual.length, expected.length);
    for (int i = 0; i < actual.length; i++) {
      byte a = actual[i];
      byte e = expected[i];
      assertEquals("not equals at index: " + i, e, a);
    }
  }

  public static <T> void assertOrderedEquals(
      final String errorMsg, @NotNull Iterable<T> actual, @NotNull T... expected) {
    Assert.assertNotNull(actual);
    Assert.assertNotNull(expected);
    assertOrderedEquals(errorMsg, actual, Arrays.asList(expected));
  }

  public static <T> void assertOrderedEquals(
      final Iterable<? extends T> actual, final Collection<? extends T> expected) {
    assertOrderedEquals(null, actual, expected);
  }

  public static <T> void assertOrderedEquals(
      final String erroMsg,
      final Iterable<? extends T> actual,
      final Collection<? extends T> expected) {
    ArrayList<T> list = new ArrayList<T>();
    for (T t : actual) {
      list.add(t);
    }
    if (!list.equals(new ArrayList<T>(expected))) {
      String expectedString = toString(expected);
      String actualString = toString(actual);
      Assert.assertEquals(erroMsg, expectedString, actualString);
      Assert.fail(
          "Warning! 'toString' does not reflect the difference.\nExpected: "
              + expectedString
              + "\nActual: "
              + actualString);
    }
  }

  public static <T> void assertOrderedCollection(T[] collection, @NotNull Consumer<T>... checkers) {
    Assert.assertNotNull(collection);
    assertOrderedCollection(Arrays.asList(collection), checkers);
  }

  public static <T> void assertSameElements(T[] collection, T... expected) {
    assertSameElements(Arrays.asList(collection), expected);
  }

  public static <T> void assertSameElements(Collection<? extends T> collection, T... expected) {
    assertSameElements(collection, Arrays.asList(expected));
  }

  public static <T> void assertSameElements(
      Collection<? extends T> collection, Collection<T> expected) {
    assertSameElements(null, collection, expected);
  }

  public static <T> void assertSameElements(
      String message, Collection<? extends T> collection, Collection<T> expected) {
    assertNotNull(collection);
    assertNotNull(expected);
    if (collection.size() != expected.size()
        || !new HashSet<T>(expected).equals(new HashSet<T>(collection))) {
      Assert.assertEquals(message, toString(expected, "\n"), toString(collection, "\n"));
      Assert.assertEquals(message, new HashSet<T>(expected), new HashSet<T>(collection));
    }
  }

  public <T> void assertContainsOrdered(Collection<? extends T> collection, T... expected) {
    assertContainsOrdered(collection, Arrays.asList(expected));
  }

  public <T> void assertContainsOrdered(
      Collection<? extends T> collection, Collection<T> expected) {
    ArrayList<T> copy = new ArrayList<T>(collection);
    copy.retainAll(expected);
    assertOrderedEquals(toString(collection), copy, expected);
  }

  public <T> void assertContainsElements(Collection<? extends T> collection, T... expected) {
    assertContainsElements(collection, Arrays.asList(expected));
  }

  public <T> void assertContainsElements(
      Collection<? extends T> collection, Collection<T> expected) {
    ArrayList<T> copy = new ArrayList<T>(collection);
    copy.retainAll(expected);
    assertSameElements(toString(collection), copy, expected);
  }

  public static String toString(Object[] collection, String separator) {
    return toString(Arrays.asList(collection), separator);
  }

  public <T> void assertDoesntContain(Collection<? extends T> collection, T... notExpected) {
    assertDoesntContain(collection, Arrays.asList(notExpected));
  }

  public <T> void assertDoesntContain(
      Collection<? extends T> collection, Collection<T> notExpected) {
    ArrayList<T> expected = new ArrayList<T>(collection);
    expected.removeAll(notExpected);
    assertSameElements(collection, expected);
  }

  public static String toString(Collection<?> collection, String separator) {
    List<String> list =
        ContainerUtil.map2List(
            collection,
            new Function<Object, String>() {
              @Override
              public String fun(final Object o) {
                return String.valueOf(o);
              }
            });
    Collections.sort(list);
    StringBuilder builder = new StringBuilder();
    boolean flag = false;
    for (final String o : list) {
      if (flag) {
        builder.append(separator);
      }
      builder.append(o);
      flag = true;
    }
    return builder.toString();
  }

  public static <T> void assertOrderedCollection(
      Collection<? extends T> collection, Consumer<T>... checkers) {
    Assert.assertNotNull(collection);
    if (collection.size() != checkers.length) {
      Assert.fail(toString(collection));
    }
    int i = 0;
    for (final T actual : collection) {
      try {
        checkers[i].consume(actual);
      } catch (AssertionFailedError e) {
        System.out.println(i + ": " + actual);
        throw e;
      }
      i++;
    }
  }

  public static <T> void assertUnorderedCollection(T[] collection, Consumer<T>... checkers) {
    assertUnorderedCollection(Arrays.asList(collection), checkers);
  }

  public static <T> void assertUnorderedCollection(
      Collection<? extends T> collection, Consumer<T>... checkers) {
    Assert.assertNotNull(collection);
    if (collection.size() != checkers.length) {
      Assert.fail(toString(collection));
    }
    Set<Consumer<T>> checkerSet = new HashSet<Consumer<T>>(Arrays.asList(checkers));
    int i = 0;
    Throwable lastError = null;
    for (final T actual : collection) {
      boolean flag = true;
      for (final Consumer<T> condition : checkerSet) {
        Throwable error = accepts(condition, actual);
        if (error == null) {
          checkerSet.remove(condition);
          flag = false;
          break;
        } else {
          lastError = error;
        }
      }
      if (flag) {
        lastError.printStackTrace();
        Assert.fail("Incorrect element(" + i + "): " + actual);
      }
      i++;
    }
  }

  private static <T> Throwable accepts(final Consumer<T> condition, final T actual) {
    try {
      condition.consume(actual);
      return null;
    } catch (Throwable e) {
      return e;
    }
  }

  public static <T> T assertInstanceOf(Object o, Class<T> aClass) {
    Assert.assertNotNull("Expected instance of: " + aClass.getName() + " actual: " + null, o);
    Assert.assertTrue(
        "Expected instance of: " + aClass.getName() + " actual: " + o.getClass().getName(),
        aClass.isInstance(o));
    @SuppressWarnings("unchecked")
    T t = (T) o;
    return t;
  }

  public static <T> T assertOneElement(Collection<T> collection) {
    Assert.assertNotNull(collection);
    Assert.assertEquals(toString(collection), 1, collection.size());
    return collection.iterator().next();
  }

  public static <T> T assertOneElement(T[] ts) {
    Assert.assertNotNull(ts);
    Assert.assertEquals(Arrays.asList(ts).toString(), 1, ts.length);
    return ts[0];
  }

  public static <T> void assertOneOf(T value, T... values) {
    boolean found = false;
    for (T v : values) {
      if (value == v || value != null && value.equals(v)) {
        found = true;
      }
    }
    Assert.assertTrue(value + " should be equal to one of " + Arrays.toString(values), found);
  }

  public static void printThreadDump() {
    PerformanceWatcher.dumpThreadsToConsole("Thread dump:");
  }

  public static void assertEmpty(final Object[] array) {
    assertOrderedEquals(array);
  }

  public static void assertNotEmpty(final Collection<?> collection) {
    if (collection == null) return;
    assertTrue(!collection.isEmpty());
  }

  public static void assertEmpty(final Collection<?> collection) {
    assertEmpty(collection.toString(), collection);
  }

  public static void assertNullOrEmpty(final Collection<?> collection) {
    if (collection == null) return;
    assertEmpty(null, collection);
  }

  public static void assertEmpty(final String s) {
    assertTrue(s, StringUtil.isEmpty(s));
  }

  public static <T> void assertEmpty(final String errorMsg, final Collection<T> collection) {
    assertOrderedEquals(errorMsg, collection);
  }

  public static void assertSize(int expectedSize, final Object[] array) {
    assertEquals(toString(Arrays.asList(array)), expectedSize, array.length);
  }

  public static void assertSize(int expectedSize, final Collection<?> c) {
    assertEquals(toString(c), expectedSize, c.size());
  }

  protected <T extends Disposable> T disposeOnTearDown(final T disposable) {
    Disposer.register(myTestRootDisposable, disposable);
    return disposable;
  }

  public static void assertSameLines(String expected, String actual) {
    String expectedText = StringUtil.convertLineSeparators(expected.trim());
    String actualText = StringUtil.convertLineSeparators(actual.trim());
    Assert.assertEquals(expectedText, actualText);
  }

  public static void assertExists(File file) {
    assertTrue("File should exist " + file, file.exists());
  }

  public static void assertDoesntExist(File file) {
    assertFalse("File should not exist " + file, file.exists());
  }

  protected String getTestName(boolean lowercaseFirstLetter) {
    String name = getName();
    return getTestName(name, lowercaseFirstLetter);
  }

  public static String getTestName(String name, boolean lowercaseFirstLetter) {
    if (name == null) {
      return "";
    }
    name = StringUtil.trimStart(name, "test");
    if (StringUtil.isEmpty(name)) {
      return "";
    }
    return lowercaseFirstLetter(name, lowercaseFirstLetter);
  }

  public static String lowercaseFirstLetter(String name, boolean lowercaseFirstLetter) {
    if (lowercaseFirstLetter && !isAllUppercaseName(name)) {
      name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
    }
    return name;
  }

  public static boolean isAllUppercaseName(String name) {
    int uppercaseChars = 0;
    for (int i = 0; i < name.length(); i++) {
      if (Character.isLowerCase(name.charAt(i))) {
        return false;
      }
      if (Character.isUpperCase(name.charAt(i))) {
        uppercaseChars++;
      }
    }
    return uppercaseChars >= 3;
  }

  protected String getTestDirectoryName() {
    final String testName = getTestName(true);
    return testName.replaceAll("_.*", "");
  }

  protected static void assertSameLinesWithFile(String filePath, String actualText) {
    String fileText;
    try {
      if (OVERWRITE_TESTDATA) {
        VfsTestUtil.overwriteTestData(filePath, actualText);
        System.out.println("File " + filePath + " created.");
      }
      fileText = FileUtil.loadFile(new File(filePath), CharsetToolkit.UTF8);
    } catch (FileNotFoundException e) {
      VfsTestUtil.overwriteTestData(filePath, actualText);
      throw new AssertionFailedError("No output text found. File " + filePath + " created.");
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    String expected = StringUtil.convertLineSeparators(fileText.trim());
    String actual = StringUtil.convertLineSeparators(actualText.trim());
    if (!Comparing.equal(expected, actual)) {
      throw new FileComparisonFailure(null, expected, actual, filePath);
    }
  }

  public static void clearFields(final Object test) throws IllegalAccessException {
    Class aClass = test.getClass();
    while (aClass != null) {
      clearDeclaredFields(test, aClass);
      aClass = aClass.getSuperclass();
    }
  }

  public static void clearDeclaredFields(Object test, Class aClass) throws IllegalAccessException {
    if (aClass == null) return;
    for (final Field field : aClass.getDeclaredFields()) {
      @NonNls final String name = field.getDeclaringClass().getName();
      if (!name.startsWith("junit.framework.") && !name.startsWith("com.intellij.testFramework.")) {
        final int modifiers = field.getModifiers();
        if ((modifiers & Modifier.FINAL) == 0
            && (modifiers & Modifier.STATIC) == 0
            && !field.getType().isPrimitive()) {
          field.setAccessible(true);
          field.set(test, null);
        }
      }
    }
  }

  @SuppressWarnings("deprecation")
  protected static void checkSettingsEqual(
      JDOMExternalizable expected, JDOMExternalizable settings, String message) throws Exception {
    if (expected == null || settings == null) return;

    Element oldS = new Element("temp");
    expected.writeExternal(oldS);
    Element newS = new Element("temp");
    settings.writeExternal(newS);

    String newString = JDOMUtil.writeElement(newS, "\n");
    String oldString = JDOMUtil.writeElement(oldS, "\n");
    Assert.assertEquals(message, oldString, newString);
  }

  public boolean isPerformanceTest() {
    String name = getName();
    return name != null && name.contains("Performance")
        || getClass().getName().contains("Performance");
  }

  public static void doPostponedFormatting(final Project project) {
    DocumentUtil.writeInRunUndoTransparentAction(
        new Runnable() {
          @Override
          public void run() {
            PsiDocumentManager.getInstance(project).commitAllDocuments();
            PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
          }
        });
  }

  protected static void checkAllTimersAreDisposed() {
    try {
      Class<?> aClass = Class.forName("javax.swing.TimerQueue");

      Method inst = aClass.getDeclaredMethod("sharedInstance");
      inst.setAccessible(true);
      Object queue = inst.invoke(null);
      Field field = aClass.getDeclaredField("firstTimer");
      field.setAccessible(true);
      Object firstTimer = field.get(queue);
      if (firstTimer != null) {
        try {
          fail("Not disposed Timer: " + firstTimer.toString() + "; queue:" + queue);
        } finally {
          field.set(queue, null);
        }
      }
    } catch (Throwable e) {
      // Ignore
    }
  }

  /**
   * Checks that code block throw corresponding exception.
   *
   * @param exceptionCase Block annotated with some exception type
   * @throws Throwable
   */
  protected void assertException(final AbstractExceptionCase exceptionCase) throws Throwable {
    assertException(exceptionCase, null);
  }

  /**
   * Checks that code block throw corresponding exception with expected error msg. If expected error
   * message is null it will not be checked.
   *
   * @param exceptionCase Block annotated with some exception type
   * @param expectedErrorMsg expected error messge
   * @throws Throwable
   */
  protected void assertException(
      final AbstractExceptionCase exceptionCase, @Nullable final String expectedErrorMsg)
      throws Throwable {
    assertExceptionOccurred(true, exceptionCase, expectedErrorMsg);
  }

  /**
   * Checks that code block doesn't throw corresponding exception.
   *
   * @param exceptionCase Block annotated with some exception type
   * @throws Throwable
   */
  protected void assertNoException(final AbstractExceptionCase exceptionCase) throws Throwable {
    assertExceptionOccurred(false, exceptionCase, null);
  }

  protected void assertNoThrowable(final Runnable closure) {
    String throwableName = null;
    try {
      closure.run();
    } catch (Throwable thr) {
      throwableName = thr.getClass().getName();
    }
    assertNull(throwableName);
  }

  private static void assertExceptionOccurred(
      boolean shouldOccur, AbstractExceptionCase exceptionCase, String expectedErrorMsg)
      throws Throwable {
    boolean wasThrown = false;
    try {
      exceptionCase.tryClosure();
    } catch (Throwable e) {
      if (shouldOccur) {
        wasThrown = true;
        final String errorMessage = exceptionCase.getAssertionErrorMessage();
        assertEquals(errorMessage, exceptionCase.getExpectedExceptionClass(), e.getClass());
        if (expectedErrorMsg != null) {
          assertEquals("Compare error messages", expectedErrorMsg, e.getMessage());
        }
      } else if (exceptionCase.getExpectedExceptionClass().equals(e.getClass())) {
        wasThrown = true;

        System.out.println("");
        e.printStackTrace(System.out);

        fail("Exception isn't expected here. Exception message: " + e.getMessage());
      } else {
        throw e;
      }
    } finally {
      if (shouldOccur && !wasThrown) {
        fail(exceptionCase.getAssertionErrorMessage());
      }
    }
  }

  protected boolean annotatedWith(@NotNull Class annotationClass) {
    Class<?> aClass = getClass();
    String methodName = "test" + getTestName(false);
    boolean methodChecked = false;
    while (aClass != null && aClass != Object.class) {
      if (aClass.getAnnotation(annotationClass) != null) return true;
      if (!methodChecked) {
        try {
          Method method = aClass.getDeclaredMethod(methodName);
          if (method.getAnnotation(annotationClass) != null) return true;
          methodChecked = true;
        } catch (NoSuchMethodException ignored) {
        }
      }
      aClass = aClass.getSuperclass();
    }
    return false;
  }

  protected String getHomePath() {
    return PathManager.getHomePath().replace(File.separatorChar, '/');
  }

  protected static boolean isInHeadlessEnvironment() {
    return GraphicsEnvironment.isHeadless();
  }

  public static void refreshRecursively(@NotNull VirtualFile file) {
    VfsUtilCore.visitChildrenRecursively(
        file,
        new VirtualFileVisitor() {
          @Override
          public boolean visitFile(@NotNull VirtualFile file) {
            file.getChildren();
            return true;
          }
        });
    file.refresh(false, true);
  }

  @NotNull
  public static Test filteredSuite(@RegExp String regexp, @NotNull Test test) {
    final Pattern pattern = Pattern.compile(regexp);
    final TestSuite testSuite = new TestSuite();
    new Processor<Test>() {

      @Override
      public boolean process(Test test) {
        if (test instanceof TestSuite) {
          for (int i = 0, len = ((TestSuite) test).testCount(); i < len; i++) {
            process(((TestSuite) test).testAt(i));
          }
        } else if (pattern.matcher(test.toString()).find()) {
          testSuite.addTest(test);
        }
        return false;
      }
    }.process(test);
    return testSuite;
  }
}
  private void doCompile(@NotNull final ModuleChunk chunk, @NotNull String outputDir)
      throws IOException {
    myCompileContext.getProgressIndicator().checkCanceled();

    if (ApplicationManager.getApplication()
        .runReadAction(
            new Computable<Boolean>() {
              public Boolean compute() {
                return chunk.getFilesToCompile().isEmpty() ? Boolean.TRUE : Boolean.FALSE;
              }
            })
        .booleanValue()) {
      return; // should not invoke javac with empty sources list
    }

    int exitValue = 0;
    try {
      final Process process = myCompiler.launchProcess(chunk, outputDir, myCompileContext);
      final long compilationStart = System.currentTimeMillis();
      final ClassParsingThread classParsingThread =
          new ClassParsingThread(isJdk6(JavaSdkUtil.getSdkForCompilation(chunk)), outputDir);
      final Future<?> classParsingThreadFuture =
          ApplicationManager.getApplication().executeOnPooledThread(classParsingThread);

      OutputParser errorParser = myCompiler.createErrorParser(outputDir, process);
      CompilerParsingThread errorParsingThread =
          errorParser == null
              ? null
              : new SynchedCompilerParsing(
                  process,
                  myCompileContext,
                  errorParser,
                  classParsingThread,
                  true,
                  errorParser.isTrimLines());
      Future<?> errorParsingThreadFuture = null;
      if (errorParsingThread != null) {
        errorParsingThreadFuture =
            ApplicationManager.getApplication().executeOnPooledThread(errorParsingThread);
      }

      OutputParser outputParser = myCompiler.createOutputParser(outputDir);
      CompilerParsingThread outputParsingThread =
          outputParser == null
              ? null
              : new SynchedCompilerParsing(
                  process,
                  myCompileContext,
                  outputParser,
                  classParsingThread,
                  false,
                  outputParser.isTrimLines());
      Future<?> outputParsingThreadFuture = null;
      if (outputParsingThread != null) {
        outputParsingThreadFuture =
            ApplicationManager.getApplication().executeOnPooledThread(outputParsingThread);
      }

      try {
        exitValue = process.waitFor();
      } catch (InterruptedException e) {
        process.destroy();
        exitValue = process.exitValue();
      } catch (Error e) {
        process.destroy();
        exitValue = process.exitValue();
        throw e;
      } finally {
        if (CompileDriver.ourDebugMode) {
          System.out.println("Compiler exit code is " + exitValue);
        }
        if (errorParsingThread != null) {
          errorParsingThread.setProcessTerminated(true);
        }
        if (outputParsingThread != null) {
          outputParsingThread.setProcessTerminated(true);
        }
        joinThread(errorParsingThreadFuture);
        joinThread(outputParsingThreadFuture);
        classParsingThread.stopParsing();
        joinThread(classParsingThreadFuture);

        registerParsingException(outputParsingThread);
        registerParsingException(errorParsingThread);
        assert outputParsingThread == null || !outputParsingThread.processing;
        assert errorParsingThread == null || !errorParsingThread.processing;
        assert classParsingThread == null || !classParsingThread.processing;
      }
    } finally {
      compileFinished(exitValue, chunk, outputDir);
      myModuleName = null;
    }
  }