package com.intellij.lang.javascript.flex.build; import com.intellij.compiler.impl.CompilerUtil; import com.intellij.flex.FlexCommonBundle; import com.intellij.flex.FlexCommonUtils; import com.intellij.flex.build.AirDescriptorOptions; import com.intellij.flex.model.bc.LinkageType; import com.intellij.flex.model.bc.OutputType; import com.intellij.javascript.flex.FlexPredefinedTagNames; import com.intellij.javascript.flex.resolve.ActionScriptClassResolver; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.flex.FlexUtils; import com.intellij.lang.javascript.flex.projectStructure.FlexProjectLevelCompilerOptionsHolder; import com.intellij.lang.javascript.flex.projectStructure.model.*; import com.intellij.lang.javascript.flex.projectStructure.model.FlexBuildConfiguration; import com.intellij.lang.javascript.flex.projectStructure.options.BCUtils; import com.intellij.lang.javascript.flex.projectStructure.options.FlexProjectRootsUtil; import com.intellij.lang.javascript.flex.sdk.FlexSdkUtils; import com.intellij.lang.javascript.flex.sdk.FlexmojosSdkType; import com.intellij.lang.javascript.psi.JSFile; import com.intellij.lang.javascript.psi.ecmal4.JSAttribute; import com.intellij.lang.javascript.psi.ecmal4.JSAttributeList; import com.intellij.lang.javascript.psi.ecmal4.JSAttributeNameValuePair; import com.intellij.lang.javascript.psi.ecmal4.JSClass; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.compiler.CompilerMessageCategory; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.LibraryOrderEntry; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.PathUtil; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.ZipUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.logging.Logger; import java.util.regex.Matcher; public class FlexCompilationUtils { private FlexCompilationUtils() { } static void deleteCacheForFile(final String filePath) throws IOException { final VirtualFile cacheFile = LocalFileSystem.getInstance().findFileByPath(filePath + ".cache"); if (cacheFile != null) { final Ref<IOException> exceptionRef = new Ref<>(); ApplicationManager.getApplication().invokeAndWait(new Runnable() { @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { if (cacheFile.exists()) { try { cacheFile.delete(this); } catch (IOException e) { exceptionRef.set(e); } } } }); } }); if (!exceptionRef.isNull()) { throw exceptionRef.get(); } } } static List<String> buildCommand(final List<String> compilerCommand, final List<VirtualFile> configFiles, final Module module, final FlexBuildConfiguration bc) { final List<String> command = new ArrayList<>(compilerCommand); for (VirtualFile configFile : configFiles) { command.add("-load-config=" + configFile.getPath()); } final Sdk sdk = bc.getSdk(); assert sdk != null; addAdditionalOptions(command, module, sdk.getHomePath(), FlexProjectLevelCompilerOptionsHolder.getInstance(module.getProject()).getProjectLevelCompilerOptions() .getAdditionalOptions()); addAdditionalOptions(command, module, sdk.getHomePath(), FlexBuildConfigurationManager.getInstance(module).getModuleLevelCompilerOptions().getAdditionalOptions()); addAdditionalOptions(command, module, sdk.getHomePath(), bc.getCompilerOptions().getAdditionalOptions()); return command; } private static void addAdditionalOptions(final List<String> command, final Module module, final String sdkHome, final String additionalOptions) { if (!StringUtil.isEmpty(additionalOptions)) { // TODO handle -option="path with spaces" for (final String s : StringUtil.split(additionalOptions, " ")) { command.add(FlexUtils.replacePathMacros(s, module, sdkHome)); } } } static List<String> getMxmlcCompcCommand(final Project project, final Sdk flexSdk, final boolean isApp) { final String mainClass = isApp ? (FlexSdkUtils.isFlex4Sdk(flexSdk) ? "flex2.tools.Mxmlc" : "flex2.tools.Compiler") : "flex2.tools.Compc"; String additionalClasspath = FileUtil.toSystemDependentName(FlexCommonUtils.getPathToBundledJar("idea-flex-compiler-fix.jar")); if (!(flexSdk.getSdkType() instanceof FlexmojosSdkType)) { additionalClasspath += File.pathSeparator + FileUtil.toSystemDependentName(flexSdk.getHomePath() + "/lib/compc.jar"); } return FlexSdkUtils.getCommandLineForSdkTool(project, flexSdk, additionalClasspath, mainClass, null); } static List<String> getASC20Command(final Project project, final Sdk flexSdk, final boolean isApp) { final String mainClass = isApp ? "com.adobe.flash.compiler.clients.MXMLC" : "com.adobe.flash.compiler.clients.COMPC"; final String additionalClasspath = flexSdk.getSdkType() instanceof FlexmojosSdkType ? null : FileUtil.toSystemDependentName(flexSdk.getHomePath() + "/lib/compiler.jar"); return FlexSdkUtils.getCommandLineForSdkTool(project, flexSdk, additionalClasspath, mainClass, null); } /** * returns <code>false</code> if compilation error found in output */ static boolean handleCompilerOutput(final FlexCompilationManager compilationManager, final FlexCompilationTask task, final String output) { boolean failureDetected = false; final List<String> lines = StringUtil.split(StringUtil.replace(output, "\r", "\n"), "\n"); for (int i = 0; i < lines.size(); i++) { final String text = lines.get(i); if (StringUtil.isEmptyOrSpaces(text) || "^".equals(text.trim())) { continue; } final String nextLine = i + 1 < lines.size() ? lines.get(i + 1) : null; if (nextLine != null && nextLine.trim().equals("^")) { // do not print line of code with error/warning continue; } final Matcher matcher = FlexCommonUtils.ERROR_PATTERN.matcher(text); if (matcher.matches()) { final String filePath = matcher.group(1); final String additionalInfo = matcher.group(2); final String line = matcher.group(3); final String column = matcher.group(4); final String type = matcher.group(5); final String message = matcher.group(6); final CompilerMessageCategory messageCategory = "Warning".equals(type) ? CompilerMessageCategory.WARNING : CompilerMessageCategory.ERROR; final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(filePath); final StringBuilder fullMessage = new StringBuilder(); if (file == null) fullMessage.append(filePath).append(": "); if (additionalInfo != null) fullMessage.append(additionalInfo).append(' '); fullMessage.append(message); compilationManager.addMessage(task, messageCategory, fullMessage.toString(), file != null ? file.getUrl() : null, line != null ? Integer.parseInt(line) : 0, column != null ? Integer.parseInt(column) : 0); failureDetected |= messageCategory == CompilerMessageCategory.ERROR; } else if (text.startsWith("Error: ") || text.startsWith("Exception in thread \"")) { final String updatedText = text.startsWith("Error: ") ? text.substring("Error: ".length()) : text; compilationManager.addMessage(task, CompilerMessageCategory.ERROR, updatedText, null, -1, -1); failureDetected = true; } else { compilationManager.addMessage(task, CompilerMessageCategory.INFORMATION, text, null, -1, -1); } } return !failureDetected; } public static void ensureOutputFileWritable(final Project project, final String filePath) { final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(filePath); if (file != null && !file.isWritable()) { ApplicationManager.getApplication().invokeAndWait(() -> ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(file)); } } public static void performPostCompileActions(final Module module, final @NotNull FlexBuildConfiguration bc, final List<String> compileInfoMessages) throws FlexCompilerException { // could be created by external build FlexCompilationManager.refreshAndFindFileInWriteAction(bc.getActualOutputFilePath()); final Sdk sdk = bc.getSdk(); assert sdk != null; LinkageType linkage = bc.getDependencies().getFrameworkLinkage(); if (linkage == LinkageType.Default) { linkage = FlexCommonUtils.getDefaultFrameworkLinkage(sdk.getVersionString(), bc.getNature()); } if (linkage == LinkageType.RSL) { handleFrameworkRsls(bc, compileInfoMessages); } if (bc.getOutputType() != OutputType.Application || BCUtils.isRLMTemporaryBC(bc) || BCUtils.isRuntimeStyleSheetBC(bc)) return; switch (bc.getTargetPlatform()) { case Web: if (bc.isUseHtmlWrapper()) { handleHtmlWrapper(module, bc); } break; case Desktop: handleAirDescriptor(module, bc, bc.getAirDesktopPackagingOptions()); break; case Mobile: if (bc.getAndroidPackagingOptions().isEnabled()) { handleAirDescriptor(module, bc, bc.getAndroidPackagingOptions()); } if (bc.getIosPackagingOptions().isEnabled()) { handleAirDescriptor(module, bc, bc.getIosPackagingOptions()); } break; } } private static void handleFrameworkRsls(final FlexBuildConfiguration bc, final List<String> compileInfoMessages) throws FlexCompilerException { final Sdk sdk = bc.getSdk(); assert sdk != null; if (!FlexSdkUtils.isAirSdkWithoutFlex(sdk) && StringUtil.compareVersionNumbers(sdk.getVersionString(), "4.8") >= 0) { final List<String> rsls = getRequiredRsls(compileInfoMessages); final Collection<File> filesToRefresh = new THashSet<>(); final String rslBaseDir = sdk.getHomePath() + "/frameworks/rsls/"; final String outputPath = PathUtil.getParentPath(bc.getActualOutputFilePath()); for (String rsl : rsls) { final File file = new File(rslBaseDir + rsl); if (file.isFile()) { try { final File toFile = new File(outputPath + '/' + rsl); FileUtil.copy(file, toFile); filesToRefresh.add(toFile); } catch (IOException e) { throw new FlexCompilerException(FlexCommonBundle.message("failed.to.copy.file", rsl, rslBaseDir, outputPath, e.getMessage())); } } } CompilerUtil.refreshIOFiles(filesToRefresh); } } private static List<String> getRequiredRsls(final List<String> compileInfoMessages) { final List<String> rsls = new ArrayList<>(); boolean rslListStarted = false; for (String message : compileInfoMessages) { if (rslListStarted) { // see tools_en.properties from Flex SDK sources if (message.startsWith("\u0020\u0020\u0020\u0020") && message.length() > 4 && !Character.isWhitespace(message.charAt(5))) { final String text = message.substring(4); final int nextSpaceIndex = text.indexOf(' '); rsls.add(nextSpaceIndex == -1 ? text : text.substring(0, nextSpaceIndex)); } else { break; } } else if ("Required RSLs:".equals(message)) { rslListStarted = true; } } return rsls; } private static void handleHtmlWrapper(final Module module, final FlexBuildConfiguration bc) throws FlexCompilerException { final VirtualFile templateDir = LocalFileSystem.getInstance().findFileByPath(bc.getWrapperTemplatePath()); if (templateDir == null || !templateDir.isDirectory()) { throw new FlexCompilerException(FlexCommonBundle.message("html.wrapper.dir.not.found", bc.getWrapperTemplatePath())); } final VirtualFile templateFile = templateDir.findChild(FlexCommonUtils.HTML_WRAPPER_TEMPLATE_FILE_NAME); if (templateFile == null) { throw new FlexCompilerException(FlexCommonBundle.message("no.index.template.html.file", bc.getWrapperTemplatePath())); } final InfoFromConfigFile info = FlexCompilerConfigFileUtil.getInfoFromConfigFile(bc.getCompilerOptions().getAdditionalConfigFilePath()); final String outputFolderPath = StringUtil.notNullize(info.getOutputFolderPath(), bc.getOutputFolder()); final String outputFileName = bc.isTempBCForCompilation() ? bc.getOutputFileName() : StringUtil.notNullize(info.getOutputFileName(), bc.getOutputFileName()); final String targetPlayer = StringUtil.notNullize(info.getTargetPlayer(), bc.getDependencies().getTargetPlayer()); final VirtualFile outputDir = LocalFileSystem.getInstance().findFileByPath(outputFolderPath); if (outputDir == null || !outputDir.isDirectory()) { throw new FlexCompilerException(FlexCommonBundle.message("output.folder.does.not.exist", outputFolderPath)); } final Ref<FlexCompilerException> exceptionRef = new Ref<>(); ApplicationManager.getApplication().invokeAndWait(new Runnable() { @Override public void run() { exceptionRef.set(ApplicationManager.getApplication().runWriteAction(new NullableComputable<FlexCompilerException>() { @Override public FlexCompilerException compute() { for (VirtualFile file : templateDir.getChildren()) { if (Comparing.equal(file, templateFile)) { final String wrapperText; try { wrapperText = VfsUtilCore.loadText(file); } catch (IOException e) { return new FlexCompilerException( FlexCommonBundle.message("failed.to.load.template.file", file.getPresentableUrl(), e.getMessage())); } if (!wrapperText.contains(FlexCommonUtils.SWF_MACRO)) { return new FlexCompilerException( FlexCommonBundle.message("no.swf.macro", FileUtil.toSystemDependentName(file.getPath()))); } final String mainClass = StringUtil.notNullize(info.getMainClass(module), bc.getMainClass()); final PsiElement jsClass = ActionScriptClassResolver.findClassByQNameStatic(mainClass, module.getModuleScope()); final String fixedText = replaceMacros(wrapperText, FileUtil.getNameWithoutExtension(outputFileName), targetPlayer, jsClass instanceof JSClass ? (JSClass)jsClass : null); final String wrapperFileName = BCUtils.getWrapperFileName(bc); try { FlexUtils.addFileWithContent(wrapperFileName, fixedText, outputDir); } catch (IOException e) { return new FlexCompilerException( FlexCommonBundle.message("failed.to.create.file.in", wrapperFileName, outputDir.getPresentableUrl(), e.getMessage())); } } else { try { file.copy(this, outputDir, file.getName()); } catch (IOException e) { return new FlexCompilerException(FlexCommonBundle.message("failed.to.copy.file", file.getName(), templateDir.getPath(), outputDir.getPath(), e.getMessage())); } } } return null; } })); } }); if (!exceptionRef.isNull()) { throw exceptionRef.get(); } } private static String replaceMacros(final String wrapperText, final String outputFileName, final String targetPlayer, final @Nullable JSClass mainClass) { final Map<String, String> replacementMap = new THashMap<>(); replacementMap.put(FlexCommonUtils.SWF_MACRO, outputFileName); replacementMap.put(FlexCommonUtils.TITLE_MACRO, outputFileName); replacementMap.put(FlexCommonUtils.APPLICATION_MACRO, outputFileName); replacementMap.put(FlexCommonUtils.BG_COLOR_MACRO, "#ffffff"); replacementMap.put(FlexCommonUtils.WIDTH_MACRO, "100%"); replacementMap.put(FlexCommonUtils.HEIGHT_MACRO, "100%"); final List<String> versionParts = StringUtil.split(targetPlayer, "."); replacementMap.put(FlexCommonUtils.VERSION_MAJOR_MACRO, versionParts.size() >= 1 ? versionParts.get(0) : "0"); replacementMap.put(FlexCommonUtils.VERSION_MINOR_MACRO, versionParts.size() >= 2 ? versionParts.get(1) : "0"); replacementMap.put(FlexCommonUtils.VERSION_REVISION_MACRO, versionParts.size() >= 3 ? versionParts.get(2) : "0"); final Ref<JSAttribute> swfMetadataRef = new Ref<>(); final PsiFile psiFile = mainClass == null ? null : mainClass.getContainingFile(); if (psiFile instanceof XmlFile) { final XmlTag rootTag = ((XmlFile)psiFile).getRootTag(); if (rootTag != null) { final String ns = rootTag.getPrefixByNamespace(JavaScriptSupportLoader.MXML_URI3) == null ? JavaScriptSupportLoader.MXML_URI : JavaScriptSupportLoader.MXML_URI3; for (XmlTag tag : rootTag.findSubTags(FlexPredefinedTagNames.METADATA, ns)) { JSResolveUtil.processInjectedFileForTag(tag, new JSResolveUtil.JSInjectedFilesVisitor() { @Override protected void process(final JSFile file) { for (PsiElement elt : file.getChildren()) { if (elt instanceof JSAttributeList) { final JSAttribute swfMetadata = ((JSAttributeList)elt).findAttributeByName("SWF"); if (swfMetadataRef.isNull() && swfMetadata != null) { swfMetadataRef.set(swfMetadata); return; } } } } }); } } } else { final JSAttributeList attributeList = mainClass == null ? null : mainClass.getAttributeList(); swfMetadataRef.set(attributeList == null ? null : attributeList.findAttributeByName("SWF")); } if (!swfMetadataRef.isNull()) { final JSAttribute swfMetadata = swfMetadataRef.get(); final JSAttributeNameValuePair titleAttr = swfMetadata.getValueByName(FlexCommonUtils.TITLE_ATTR); ContainerUtil.putIfNotNull(FlexCommonUtils.TITLE_MACRO, titleAttr == null ? null : titleAttr.getSimpleValue(), replacementMap); final JSAttributeNameValuePair bgColorAttr = swfMetadata.getValueByName(FlexCommonUtils.BG_COLOR_ATTR); ContainerUtil.putIfNotNull(FlexCommonUtils.BG_COLOR_MACRO, bgColorAttr == null ? null : bgColorAttr.getSimpleValue(), replacementMap); final JSAttributeNameValuePair widthAttr = swfMetadata.getValueByName(FlexCommonUtils.WIDTH_ATTR); ContainerUtil.putIfNotNull(FlexCommonUtils.WIDTH_MACRO, widthAttr == null ? null : widthAttr.getSimpleValue(), replacementMap); final JSAttributeNameValuePair heightAttr = swfMetadata.getValueByName(FlexCommonUtils.HEIGHT_ATTR); ContainerUtil.putIfNotNull(FlexCommonUtils.HEIGHT_MACRO, heightAttr == null ? null : heightAttr.getSimpleValue(), replacementMap); } return FlexCommonUtils.replace(wrapperText, replacementMap); } private static void handleAirDescriptor(final Module module, final FlexBuildConfiguration bc, final AirPackagingOptions packagingOptions) throws FlexCompilerException { if (packagingOptions.isUseGeneratedDescriptor()) { final boolean android = packagingOptions instanceof AndroidPackagingOptions; final boolean ios = packagingOptions instanceof IosPackagingOptions; generateAirDescriptor(module, bc, BCUtils.getGeneratedAirDescriptorName(bc, packagingOptions), android, ios); } else { copyAndFixCustomAirDescriptor(bc, packagingOptions); } } private static void generateAirDescriptor(final Module module, final FlexBuildConfiguration bc, final String descriptorFileName, final boolean android, final boolean ios) throws FlexCompilerException { final Ref<FlexCompilerException> exceptionRef = new Ref<>(); final Runnable runnable = () -> { final Sdk sdk = bc.getSdk(); assert sdk != null; final String outputFilePath = bc.getActualOutputFilePath(); final String outputFolderPath = PathUtil.getParentPath(outputFilePath); final VirtualFile outputFolder = LocalFileSystem.getInstance().findFileByPath(outputFolderPath); if (outputFolder == null) { exceptionRef.set(new FlexCompilerException(FlexCommonBundle.message("output.folder.does.not.exist", FileUtil.toSystemDependentName(outputFolderPath)))); return; } final String airVersion = FlexCommonUtils.getAirVersion(sdk.getHomePath(), sdk.getVersionString()); if (airVersion == null) { exceptionRef.set(new FlexCompilerException(FlexCommonBundle.message("failed.to.get.air.sdk.version.use.custom.descriptor"))); return; } final String appId = FlexCommonUtils.fixApplicationId(bc.getMainClass()); final String appName = StringUtil.getShortName(bc.getMainClass()); final String swfName = PathUtil.getFileName(outputFilePath); final String[] extensions = getAirExtensionIDs(ModuleRootManager.getInstance(module), bc.getDependencies()); ApplicationManager.getApplication().runWriteAction(() -> { try { final AirDescriptorOptions descriptorOptions = new AirDescriptorOptions(airVersion, appId, appName, swfName, extensions, android, ios); final String descriptorText = descriptorOptions.getAirDescriptorText(); FlexUtils.addFileWithContent(descriptorFileName, descriptorText, outputFolder); } catch (IOException e) { exceptionRef.set(new FlexCompilerException(FlexCommonBundle.message("failed.to.generate.air.descriptor", e.getMessage()))); } }); }; ApplicationManager.getApplication().invokeAndWait(runnable); if (!exceptionRef.isNull()) { throw exceptionRef.get(); } } public static Collection<VirtualFile> getANEFiles(final ModuleRootModel moduleRootModel, final Dependencies dependencies) { final Collection<VirtualFile> result = new ArrayList<>(); for (DependencyEntry entry : dependencies.getEntries()) { if (entry instanceof ModuleLibraryEntry) { final LibraryOrderEntry orderEntry = FlexProjectRootsUtil.findOrderEntry((ModuleLibraryEntry)entry, moduleRootModel); if (orderEntry != null) { for (VirtualFile libFile : orderEntry.getRootFiles(OrderRootType.CLASSES)) { addIfANE(result, libFile); } } } else if (entry instanceof SharedLibraryEntry) { final Library library = FlexProjectRootsUtil.findOrderEntry(moduleRootModel.getModule().getProject(), (SharedLibraryEntry)entry); if (library != null) { for (VirtualFile libFile : library.getFiles((OrderRootType.CLASSES))) { addIfANE(result, libFile); } } } } return result; } private static void addIfANE(final Collection<VirtualFile> result, final VirtualFile libFile) { final VirtualFile realFile = FlexCompilerHandler.getRealFile(libFile); if (realFile != null && !realFile.isDirectory() && "ane".equalsIgnoreCase(realFile.getExtension())) { result.add(realFile); } } public static String[] getAirExtensionIDs(final ModuleRootModel moduleRootModel, final Dependencies dependencies) { final Collection<VirtualFile> aneFiles = getANEFiles(moduleRootModel, dependencies); final Collection<String> extensionIDs = new ArrayList<>(); for (VirtualFile aneFile : aneFiles) { final String extensionId = getExtensionId(aneFile); ContainerUtil.addIfNotNull(extensionIDs, extensionId); } return extensionIDs.toArray(new String[extensionIDs.size()]); } @Nullable private static String getExtensionId(final VirtualFile aneFile) { final VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(aneFile); if (jarRoot == null) return null; final VirtualFile xmlFile = VfsUtil.findRelativeFile("META-INF/ANE/extension.xml", jarRoot); if (xmlFile == null) return null; try { return FlexUtils.findXMLElement(xmlFile.getInputStream(), "<extension><id>"); } catch (IOException e) { return null; } } public static void unzipANEFiles(final Collection<VirtualFile> aneFiles, final ProgressIndicator indicator) { final File baseDir = new File(getPathToUnzipANE()); if (!baseDir.exists()) { if (!baseDir.mkdir()) { Logger.getLogger(FlexCompilationUtils.class.getName()).warning("Failed to create " + baseDir.getPath()); return; } } for (VirtualFile file : aneFiles) { if (indicator != null && indicator.isCanceled()) return; final File subDir = new File(baseDir, file.getName()); if (!subDir.exists()) { if (!subDir.mkdir()) { Logger.getLogger(FlexCompilationUtils.class.getName()).warning("Failed to create " + baseDir.getPath()); continue; } } try { ZipUtil.extract(new File(file.getPath()), subDir, null, true); } catch (IOException e) { Logger.getLogger(FlexCompilationUtils.class.getName()).warning("Failed to unzip " + file.getPath() + " to " + baseDir.getPath()); } } } public static void deleteUnzippedANEFiles() { FileUtil.delete(new File(getPathToUnzipANE())); } public static String getPathToUnzipANE() { return FileUtil.getTempDirectory() + File.separator + "IntelliJ_ANE_unzipped"; } private static void copyAndFixCustomAirDescriptor(final FlexBuildConfiguration bc, final AirPackagingOptions packagingOptions) throws FlexCompilerException { final String customDescriptorPath = packagingOptions.getCustomDescriptorPath(); final VirtualFile descriptorTemplateFile = LocalFileSystem.getInstance().findFileByPath(customDescriptorPath); if (descriptorTemplateFile == null) { throw new FlexCompilerException(FlexCommonBundle.message("air.descriptor.not.found", customDescriptorPath)); } final String outputFilePath = bc.getActualOutputFilePath(); final String outputFolderPath = PathUtil.getParentPath(outputFilePath); final VirtualFile outputFolder = LocalFileSystem.getInstance().findFileByPath(outputFolderPath); if (outputFolder == null) { throw new FlexCompilerException(FlexCommonBundle.message("output.folder.does.not.exist", outputFolderPath)); } final Ref<FlexCompilerException> exceptionRef = new Ref<>(); ApplicationManager.getApplication().invokeAndWait(() -> ApplicationManager.getApplication().runWriteAction(() -> { try { final String content = fixInitialContent(descriptorTemplateFile, PathUtil.getFileName(outputFilePath)); final String descriptorFileName = bc.isTempBCForCompilation() ? BCUtils.getGeneratedAirDescriptorName(bc, packagingOptions) : descriptorTemplateFile.getName(); FlexUtils.addFileWithContent(descriptorFileName, content, outputFolder); } catch (FlexCompilerException e) { exceptionRef.set(e); } catch (IOException e) { exceptionRef.set(new FlexCompilerException(FlexCommonBundle.message("failed.to.copy.air.descriptor", e.getMessage()))); } })); if (!exceptionRef.isNull()) { throw exceptionRef.get(); } } private static String fixInitialContent(final VirtualFile descriptorFile, final String swfName) throws FlexCompilerException { try { final Document document; try { document = JDOMUtil.loadDocument(descriptorFile.getInputStream()); } catch (IOException e) { throw new FlexCompilerException("Failed to read AIR descriptor content: " + e.getMessage(), descriptorFile.getUrl(), -1, -1); } final Element rootElement = document.getRootElement(); if (!"application".equals(rootElement.getName())) { throw new FlexCompilerException("AIR descriptor file has incorrect root tag", descriptorFile.getUrl(), -1, -1); } Element initialWindowElement = rootElement.getChild("initialWindow", rootElement.getNamespace()); if (initialWindowElement == null) { initialWindowElement = new Element("initialWindow", rootElement.getNamespace()); rootElement.addContent(initialWindowElement); } Element contentElement = initialWindowElement.getChild("content", rootElement.getNamespace()); if (contentElement == null) { contentElement = new Element("content", rootElement.getNamespace()); initialWindowElement.addContent(contentElement); } contentElement.setText(swfName); return JDOMUtil.writeDocument(document, SystemProperties.getLineSeparator()); } catch (JDOMException e) { throw new FlexCompilerException("AIR descriptor file has incorrect format: " + e.getMessage(), descriptorFile.getUrl(), -1, -1); } } }