/* * Copyright 2003-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.util; import jetbrains.mps.vfs.path.Path; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jdom.Document; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.annotations.Internal; import org.jetbrains.mps.annotations.Singleton; import java.io.File; import java.io.FilenameFilter; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Responsible for different predefined paths in the distribution layout */ @Singleton public final class PathManager { private static final Logger LOG = LogManager.getLogger(PathManager.class); private static final String FILE = "file"; public static final String JAR = "jar"; private static final String JAR_DELIMITER = "!"; public static final String DOT_JAR = ".jar"; private static final String PROTOCOL_DELIMITER = ":"; private static final String PLUGINS_PATH = "plugins"; private static final String PROPERTIES_FILE_NAME = "idea.properties"; private static String ourHomePath; private static String ourIdeaPath; public static final FilenameFilter JAR_FILE_FILTER = (dir, name) -> name.endsWith(DOT_JAR); private PathManager() { } public static String getHomePath() { if (ourHomePath != null) { return ourHomePath; } String rootPath = getContainingJar(PathManager.class); File root = new File(rootPath); root = root.getAbsoluteFile(); if (rootPath.endsWith(DOT_JAR)) { // {mps_home}/lib root = root.getParentFile(); if (root != null) { // {mps_home} root = root.getParentFile(); } } else { while ((!isMpsDir(root)) && (root.getParentFile() != null)) { root = root.getParentFile(); } } ourHomePath = root.getAbsolutePath(); if (ourHomePath.equals("/")) { throw new IllegalStateException("cannot detect MPS location"); } return ourHomePath; } /** * Defines whether we are starting from sources not from distribution */ @Internal public static boolean isFromSources() { return !getContainingJar(PathManager.class).endsWith(Path.DOT_JAR); } private static String getContainingJar(Class aClass) { return getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class"); } public static String getIdeaPath() { if (ourIdeaPath != null) { return ourIdeaPath; } // {idea_home}/lib/jdom.jar String rootPath = getContainingJar(Document.class); if (rootPath == null) { ourIdeaPath = getHomePath(); return ourIdeaPath; } File root = new File(rootPath); root = root.getAbsoluteFile(); // {idea_home}/lib root = root.getParentFile(); if (root != null) { // {idea_home} root = root.getParentFile(); } if (root == null) { ourIdeaPath = getHomePath(); } else { ourIdeaPath = root.getAbsolutePath(); } return ourIdeaPath; } public static String[] getHomePaths() { if (getHomePath().equals(getIdeaPath())) { return new String[]{getHomePath()}; } return new String[]{getHomePath(), getIdeaPath()}; } public static Collection<String> getBootstrapPaths() { Collection<String> paths = getBootstrapPathsFromLibFolder(); if (new File(getCorePath()).exists()) { paths.add(getCorePath()); } if (new File(getEditorPath()).exists()) { paths.add(getEditorPath()); } return Collections.unmodifiableCollection(paths); } @NotNull private static Collection<String> getBootstrapPathsFromLibFolder() { List<String> paths = new ArrayList<String>(); File libDir = new File(getLibPath()); if (libDir.exists() && libDir.isDirectory()) { for (File jar : libDir.listFiles(JAR_FILE_FILTER)) { paths.add(jar.getAbsolutePath()); } } return paths; } private static String getLibPath() { return getHomePath() + File.separator + "lib"; } public static String getLanguagesPath() { return getHomePath() + File.separator + "languages"; } public static String getWorkbenchPath() { return getHomePath() + File.separator + "workbench"; } public static String getCorePath() { return getHomePath() + File.separator + "core"; } public static String getEditorPath() { return getHomePath() + File.separator + "editor"; } private static boolean isMpsDir(File file) { return new File(file, "bin" + File.separator + PROPERTIES_FILE_NAME).exists(); } /** * Attempts to detect classpath entry which contains given resource */ public static String getResourceRoot(Class context, String path) { URL url = context.getResource(path); if (url == null) { url = ClassLoader.getSystemResource(path.substring(1)); } if (url == null) { return null; } return extractRoot(url, path); } /** * Attempts to extract classpath entry part from passed URL. */ private static String extractRoot(URL resourceURL, String resourcePath) { if (!(resourcePath.startsWith("/") || resourcePath.startsWith("\\"))) { LOG.error("precondition failed for" + resourcePath); return null; } String protocol = resourceURL.getProtocol(); String resultPath = null; if (FILE.equals(protocol)) { String path = resourceURL.getFile(); String testPath = path.replace('\\', '/').toLowerCase(); String testResourcePath = resourcePath.replace('\\', '/').toLowerCase(); if (testPath.endsWith(testResourcePath)) { resultPath = path.substring(0, path.length() - resourcePath.length()); } } else if (JAR.equals(protocol)) { String fullPath = resourceURL.getFile(); int delimiter = fullPath.indexOf(JAR_DELIMITER); if (delimiter >= 0) { String archivePath = fullPath.substring(0, delimiter); if (archivePath.startsWith(FILE + PROTOCOL_DELIMITER)) { resultPath = archivePath.substring(FILE.length() + PROTOCOL_DELIMITER.length()); } } } if (resultPath != null && resultPath.endsWith(File.separator)) { resultPath = resultPath.substring(0, resultPath.length() - 1); } resultPath = resultPath != null ? StringUtil.replace(resultPath, "%20", " ") : null; return resultPath; } public static String getPreInstalledPluginsPath() { return getHomePath() + File.separator + PLUGINS_PATH; } public static String getUserDir() { return System.getProperty("user.dir"); } }