package com.intellij.flex.model.bc; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.PathUtilRt; import gnu.trove.THashMap; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.module.JpsModuleSourceRoot; import org.jetbrains.jps.util.JpsPathUtil; import java.io.File; import java.io.IOException; import java.util.Map; public class InfoFromConfigFile { public static InfoFromConfigFile DEFAULT = new InfoFromConfigFile(null, null, null, null, null); private static final Map<String, Pair<Long, InfoFromConfigFile>> ourCache = new THashMap<>(); private final @Nullable File myConfigFile; private final @Nullable String myMainClassPath; private boolean myMainClassInitialized = false; private @Nullable String myMainClass; private final @Nullable String myOutputFileName; private final @Nullable String myOutputFolderPath; private final @Nullable String myTargetPlayer; private InfoFromConfigFile(final @Nullable File configFile, final @Nullable String mainClassPath, final @Nullable String outputFileName, final @Nullable String outputFolderPath, final @Nullable String targetPlayer) { myConfigFile = configFile; myMainClassPath = mainClassPath; myOutputFileName = outputFileName; myOutputFolderPath = outputFolderPath; myTargetPlayer = targetPlayer; } @Nullable public String getMainClass(final JpsModule module) { if (!myMainClassInitialized && myConfigFile != null && myConfigFile.isFile()) { myMainClass = myMainClassPath == null ? null : getMainClassByPath(module, myMainClassPath, myConfigFile.getParent()); } myMainClassInitialized = true; return myMainClass; } @Nullable public String getOutputFileName() { return myOutputFileName; } @Nullable public String getOutputFolderPath() { return myOutputFolderPath; } @Nullable public String getTargetPlayer() { return myTargetPlayer; } private static String getMainClassByPath(final JpsModule module, final String mainClassPath, final String baseDir) { if (mainClassPath.isEmpty()) return "unknown"; File mainClassFile = new File(mainClassPath); if (!mainClassFile.isFile()) { mainClassFile = new File(baseDir + File.pathSeparator + mainClassPath); } if (!mainClassFile.isFile()) { return FileUtil.getNameWithoutExtension(FileUtil.getNameWithoutExtension(PathUtilRt.getFileName(mainClassPath))); } String mainClassCanonicalPath; try { mainClassCanonicalPath = FileUtil.toSystemIndependentName(mainClassFile.getCanonicalPath()); } catch (IOException e) { mainClassCanonicalPath = FileUtil.toSystemIndependentName(mainClassFile.getPath()); } for (JpsModuleSourceRoot sourceRoot : module.getSourceRoots()) { final String sourcePath = JpsPathUtil.urlToPath(sourceRoot.getUrl()); if (FileUtil.isAncestor(sourcePath, mainClassCanonicalPath, true)) { final String relativePath = FileUtil.getRelativePath(sourcePath, mainClassCanonicalPath, '/'); if (relativePath != null) { return FileUtil.getNameWithoutExtension(relativePath).replace("/", "."); } } } return FileUtil.getNameWithoutExtension(mainClassCanonicalPath); } @NotNull public static InfoFromConfigFile getInfoFromConfigFile(final String configFilePath) { final File configFile = configFilePath.isEmpty() ? null : new File(configFilePath); if (configFile == null || !configFile.isFile()) { ourCache.remove(configFilePath); return DEFAULT; } String canonicalPath; try { canonicalPath = configFile.getCanonicalPath(); } catch (IOException e) { canonicalPath = configFile.getPath(); } Pair<Long, InfoFromConfigFile> data = ourCache.get(canonicalPath); final Long currentTimestamp = configFile.lastModified(); final Long cachedTimestamp = data == null ? null : data.first; if (cachedTimestamp == null || !cachedTimestamp.equals(currentTimestamp)) { ourCache.remove(canonicalPath); String mainClassPath = null; String outputPath = null; String targetPlayer = null; try { final Element rootElement = JDOMUtil.load(configFile); final Element fileSpecsElement = rootElement.getChild("file-specs", rootElement.getNamespace()); mainClassPath = fileSpecsElement == null ? null : fileSpecsElement.getChildTextNormalize("path-element", rootElement.getNamespace()); outputPath = rootElement.getChildTextNormalize("output", rootElement.getNamespace()); if (outputPath != null && !FileUtil.isAbsolute(outputPath)) { try { outputPath = FileUtil.toSystemIndependentName(new File(configFile.getParent(), outputPath).getCanonicalPath()); } catch (IOException e) { outputPath = FileUtil.toSystemIndependentName(new File(configFile.getParent(), outputPath).getAbsolutePath()); } } targetPlayer = rootElement.getChildTextNormalize("target-player", rootElement.getNamespace()); } catch (IOException | JDOMException ignore) {/*ignore*/ } final String outputFileName = outputPath == null ? null : PathUtilRt.getFileName(outputPath); final String outputFolderPath = outputPath == null ? null : PathUtilRt.getParentPath(outputPath); data = Pair.create(currentTimestamp, new InfoFromConfigFile(configFile, mainClassPath, outputFileName, outputFolderPath, targetPlayer)); ourCache.put(canonicalPath, data); } return data.second; } }