001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.utils;
018    
019    import com.intellij.openapi.application.ApplicationManager;
020    import com.intellij.openapi.application.PathManager;
021    import com.intellij.openapi.util.io.FileUtil;
022    import com.intellij.openapi.vfs.VirtualFile;
023    import com.intellij.openapi.vfs.VirtualFileManager;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.jps.model.java.impl.JavaSdkUtil;
026    
027    import java.io.File;
028    import java.util.List;
029    
030    public class PathUtil {
031    
032        public static final String JPS_KOTLIN_HOME_PROPERTY = "jps.kotlin.home";
033    
034        public static final String JS_LIB_JAR_NAME = "kotlin-jslib.jar";
035        public static final String JS_LIB_SRC_JAR_NAME = "kotlin-jslib-sources.jar";
036        public static final String JDK_ANNOTATIONS_JAR = "kotlin-jdk-annotations.jar";
037        public static final String ANDROID_SDK_ANNOTATIONS_JAR = "kotlin-android-sdk-annotations.jar";
038        public static final String KOTLIN_JAVA_RUNTIME_JAR = "kotlin-runtime.jar";
039        public static final String KOTLIN_JAVA_REFLECT_JAR = "kotlin-reflect.jar";
040        public static final String KOTLIN_JAVA_RUNTIME_SRC_JAR = "kotlin-runtime-sources.jar";
041        public static final String KOTLIN_COMPILER_JAR = "kotlin-compiler.jar";
042    
043        public static final String HOME_FOLDER_NAME = "kotlinc";
044        private static final File NO_PATH = new File("<no_path>");
045    
046        private PathUtil() {}
047    
048        @NotNull
049        public static KotlinPaths getKotlinPathsForIdeaPlugin() {
050            return ApplicationManager.getApplication().isUnitTestMode()
051                ? getKotlinPathsForDistDirectory()
052                : new KotlinPathsFromHomeDir(getCompilerPathForIdeaPlugin());
053        }
054    
055        @NotNull
056        public static KotlinPaths getKotlinPathsForJpsPlugin() {
057            // When JPS is run on TeamCity, it can not rely on Kotlin plugin layout,
058            // so the path to Kotlin is specified in a system property
059            String jpsKotlinHome = System.getProperty(JPS_KOTLIN_HOME_PROPERTY);
060            if (jpsKotlinHome != null) {
061                return new KotlinPathsFromHomeDir(new File(jpsKotlinHome));
062            }
063            return new KotlinPathsFromHomeDir(getCompilerPathForJpsPlugin());
064        }
065    
066        @NotNull
067        public static KotlinPaths getKotlinPathsForJpsPluginOrJpsTests() {
068            if ("true".equalsIgnoreCase(System.getProperty("kotlin.jps.tests"))) {
069                return getKotlinPathsForDistDirectory();
070            }
071            return getKotlinPathsForJpsPlugin();
072        }
073    
074        @NotNull
075        public static KotlinPaths getKotlinPathsForCompiler() {
076            if (!getPathUtilJar().isFile()) {
077                // Not running from a jar, i.e. it is it must be a unit test
078                return getKotlinPathsForDistDirectory();
079            }
080            return new KotlinPathsFromHomeDir(getCompilerPathForCompilerJar());
081        }
082    
083        @NotNull
084        public static KotlinPaths getKotlinPathsForDistDirectory() {
085            return new KotlinPathsFromHomeDir(new File("dist", HOME_FOLDER_NAME));
086        }
087    
088        @NotNull
089        private static File getCompilerPathForCompilerJar() {
090            File jar = getPathUtilJar();
091    
092            if (!jar.exists()) return NO_PATH;
093    
094            if (jar.getName().equals(KOTLIN_COMPILER_JAR)) {
095                File lib = jar.getParentFile();
096                return lib.getParentFile();
097            }
098    
099            return NO_PATH;
100        }
101    
102        @NotNull
103        private static File getCompilerPathForJpsPlugin() {
104            File jar = getPathUtilJar();
105    
106            if (!jar.exists()) return NO_PATH;
107    
108            if (jar.getName().equals("kotlin-jps-plugin.jar")) {
109                File pluginHome = jar.getParentFile().getParentFile().getParentFile();
110                return new File(pluginHome, HOME_FOLDER_NAME);
111            }
112    
113            return NO_PATH;
114        }
115    
116        @NotNull
117        private static File getCompilerPathForIdeaPlugin() {
118            File jar = getPathUtilJar();
119    
120            if (!jar.exists()) return NO_PATH;
121    
122            if (jar.getName().equals("kotlin-plugin.jar")) {
123                File lib = jar.getParentFile();
124                File pluginHome = lib.getParentFile();
125    
126                return new File(pluginHome, HOME_FOLDER_NAME);
127            }
128    
129            return NO_PATH;
130        }
131    
132        @NotNull
133        public static File getPathUtilJar() {
134            return getResourcePathForClass(PathUtil.class);
135        }
136    
137        @NotNull
138        public static File getResourcePathForClass(@NotNull Class aClass) {
139            String path = "/" + aClass.getName().replace('.', '/') + ".class";
140            String resourceRoot = PathManager.getResourceRoot(aClass, path);
141            if (resourceRoot == null) {
142                throw new IllegalStateException("Resource not found: " + path);
143            }
144            return new File(resourceRoot).getAbsoluteFile();
145        }
146    
147        @NotNull
148        public static VirtualFile jarFileOrDirectoryToVirtualFile(@NotNull File file) {
149            if (file.exists()) {
150                if (file.isDirectory()) {
151                    return VirtualFileManager.getInstance()
152                            .findFileByUrl("file://" + FileUtil.toSystemIndependentName(file.getAbsolutePath()));
153                }
154                else {
155                    return VirtualFileManager.getInstance().findFileByUrl("jar://" + FileUtil.toSystemIndependentName(file.getAbsolutePath()) + "!/");
156                }
157            }
158            else {
159                throw new IllegalStateException("Path " + file + " does not exist.");
160            }
161        }
162    
163        @NotNull
164        public static List<File> getJdkClassesRoots() {
165            return JavaSdkUtil.getJdkClassesRoots(new File(System.getProperty("java.home")), true);
166        }
167    }