public static File getOrCreateConfigFile(
      final JpsFlexBuildConfiguration bc, final ProjectDescriptor projectDescriptor)
      throws IOException {
    final CompilerConfigGeneratorRt generator =
        new CompilerConfigGeneratorRt(
            bc,
            bc.getModule().getProperties().getModuleLevelCompilerOptions(),
            JpsFlexProjectLevelCompilerOptionsExtension.getProjectLevelCompilerOptions(
                bc.getModule().getProject()),
            projectDescriptor);
    String text = generator.generateConfigFileText();

    if (bc.isTempBCForCompilation()) {
      final JpsFlexBuildConfiguration originalBC =
          bc.getModule().getProperties().findConfigurationByName(bc.getName());
      final boolean makeExternalLibsMerged =
          FlexCommonUtils.isFlexUnitBC(bc)
              || (originalBC != null && originalBC.getOutputType() == OutputType.Library);
      final boolean makeIncludedLibsMerged = FlexCommonUtils.isRuntimeStyleSheetBC(bc);
      text =
          FlexCompilerConfigFileUtilBase.mergeWithCustomConfigFile(
              text,
              bc.getCompilerOptions().getAdditionalConfigFilePath(),
              makeExternalLibsMerged,
              makeIncludedLibsMerged);
    }

    final String name = getConfigFileName(bc, FlexCommonUtils.getBCSpecifier(bc));
    return getOrCreateConfigFile(name, text);
  }
  private void addLibClasses(final Element rootElement) throws IOException {
    final JpsCompilerExcludes excludes =
        JpsJavaExtensionService.getInstance()
            .getOrCreateCompilerConfiguration(myModule.getProject())
            .getCompilerExcludes();
    final Ref<Boolean> noClasses = new Ref<Boolean>(true);

    for (JpsTypedModuleSourceRoot srcRoot : myModule.getSourceRoots(JavaSourceRootType.SOURCE)) {
      final File srcFolder = JpsPathUtil.urlToFile(srcRoot.getUrl());
      if (srcFolder.isDirectory()) {
        processFilesRecursively(
            srcFolder,
            new Processor<File>() {
              public boolean process(final File file) {
                if (myProjectDescriptor.getIgnoredFileIndex().isIgnored(file.getName()))
                  return false;
                if (file.isDirectory()) return true;
                if (!FlexCommonUtils.isSourceFile(file.getName())) return true;
                if (excludes.isExcluded(file)) return true;

                String packageRelativePath =
                    FileUtil.getRelativePath(srcFolder, file.getParentFile());
                assert packageRelativePath != null : srcFolder.getPath() + ": " + file.getPath();
                if (packageRelativePath.equals(".")) packageRelativePath = "";

                final String packageName = packageRelativePath.replace(File.separatorChar, '.');
                final String qName =
                    StringUtil.getQualifiedName(
                        packageName, FileUtil.getNameWithoutExtension(file));

                if (isSourceFileWithPublicDeclaration(file)) {
                  addOption(rootElement, CompilerOptionInfo.INCLUDE_CLASSES_INFO, qName);
                  noClasses.set(false);
                }

                return true;
              }
            });
      }
    }

    if (noClasses.get()
        && myBC.getCompilerOptions().getFilesToIncludeInSWC().isEmpty()
        && !Utils.IS_TEST_MODE) {
      throw new IOException(
          FlexCommonBundle.message(
              "nothing.to.compile.in.library", myModule.getName(), myBC.getName()));
    }
  }
 private static String getConfigFileName(
     final JpsFlexBuildConfiguration bc, final @Nullable String postfix) {
   final String prefix = "idea"; // PlatformUtils.getPlatformPrefix().toLowerCase()
   final String hash1 =
       Integer.toHexString(
               (SystemProperties.getUserName() + bc.getModule().getProject().getName()).hashCode())
           .toUpperCase();
   final String hash2 =
       Integer.toHexString(
               (bc.getModule().getName() + StringUtil.notNullize(bc.getName())).hashCode())
           .toUpperCase();
   return prefix
       + "-"
       + hash1
       + "-"
       + hash2
       + (postfix == null ? ".xml" : ("-" + StringUtil.replaceChar(postfix, ' ', '-') + ".xml"));
 }
  private void addInputOutputPaths(final Element rootElement) throws IOException {
    if (myBC.getOutputType() == OutputType.Library) {
      addFilesIncludedInSwc(rootElement);

      if (!myFlexmojos) {
        addLibClasses(rootElement);
      }
    } else {
      final InfoFromConfigFile info =
          InfoFromConfigFile.getInfoFromConfigFile(
              myBC.getCompilerOptions().getAdditionalConfigFilePath());

      final String pathToMainClassFile =
          myCSS
              ? myBC.getMainClass()
              : myFlexUnit
                  ? getPathToFlexUnitMainClass(
                      myProjectDescriptor, myBC.getNature(), myBC.getMainClass())
                  : FlexCommonUtils.getPathToMainClassFile(myBC.getMainClass(), myModule);

      if (pathToMainClassFile.isEmpty()
          && info.getMainClass(myModule) == null
          && !Utils.IS_TEST_MODE) {
        throw new IOException(
            FlexCommonBundle.message(
                "bc.incorrect.main.class",
                myBC.getMainClass(),
                myBC.getName(),
                myModule.getName()));
      }

      if (!pathToMainClassFile.isEmpty()) {
        addOption(
            rootElement,
            CompilerOptionInfo.MAIN_CLASS_INFO,
            FileUtil.toSystemIndependentName(pathToMainClassFile));
      }
    }

    addOption(rootElement, CompilerOptionInfo.OUTPUT_PATH_INFO, myBC.getActualOutputFilePath());
  }
 private CompilerConfigGeneratorRt(
     final @NotNull JpsFlexBuildConfiguration bc,
     final @NotNull JpsFlexModuleOrProjectCompilerOptions moduleLevelCompilerOptions,
     final @NotNull JpsFlexModuleOrProjectCompilerOptions projectLevelCompilerOptions,
     final @NotNull ProjectDescriptor projectDescriptor)
     throws IOException {
   myProjectDescriptor = projectDescriptor;
   myModule = bc.getModule();
   myBC = bc;
   myFlexUnit = FlexCommonUtils.isFlexUnitBC(myBC);
   myCSS = FlexCommonUtils.isRuntimeStyleSheetBC(bc);
   mySdk = bc.getSdk();
   if (mySdk == null) {
     throw new IOException(
         FlexCommonBundle.message(
             "sdk.not.set.for.bc.0.of.module.1", bc.getName(), bc.getModule().getName()));
   }
   myFlexmojos = mySdk.getSdkType() == JpsFlexmojosSdkType.INSTANCE;
   myModuleLevelCompilerOptions = moduleLevelCompilerOptions;
   myProjectLevelCompilerOptions = projectLevelCompilerOptions;
 }
  @Nullable
  private static String getCustomLinkReportPath(final JpsFlexBuildConfiguration rlmBC) {
    final JpsFlexBuildConfiguration appBC =
        rlmBC.getModule().getProperties().findConfigurationByName(rlmBC.getName());
    if (appBC != null) {
      final List<String> linkReports =
          FlexCommonUtils.getOptionValues(
              appBC.getCompilerOptions().getAdditionalOptions(), "link-report");
      if (!linkReports.isEmpty()) {
        final String path = linkReports.get(0);
        if (new File(path).isFile()) return path;
        final String absPath =
            FlexCommonUtils.getFlexCompilerWorkDirPath(appBC.getModule().getProject()) + "/" + path;
        if (new File(absPath).isFile()) return absPath;
      } else {
        final String configFilePath = appBC.getCompilerOptions().getAdditionalConfigFilePath();
        if (!configFilePath.isEmpty()) {
          final File configFile = new File(configFilePath);
          if (configFile.isFile()) {
            final String path =
                FlexCommonUtils.findXMLElement(configFile, "<flex-config><link-report>");
            if (path != null) {
              if (new File(path).isFile()) return path;
              // I have no idea why Flex compiler treats path relative to source root for
              // "link-report" option
              for (JpsModuleSourceRoot srcRoot :
                  appBC.getModule().getSourceRoots(JavaSourceRootType.SOURCE)) {
                final String absPath = srcRoot.getFile().getPath() + "/" + path;
                if (new File(absPath).isFile()) return absPath;
              }
            }
          }
        }
      }
    }

    return null;
  }