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 HOME_FOLDER_NAME = "kotlinc";
042    
043        private static final File NO_PATH = new File("<no_path>");
044    
045        private PathUtil() {}
046    
047        @NotNull
048        public static KotlinPaths getKotlinPathsForIdeaPlugin() {
049            return ApplicationManager.getApplication().isUnitTestMode()
050                ? getKotlinPathsForDistDirectory()
051                : new KotlinPathsFromHomeDir(getCompilerPathForIdeaPlugin());
052        }
053    
054        @NotNull
055        public static KotlinPaths getKotlinPathsForJpsPlugin() {
056            // When JPS is run on TeamCity, it can not rely on Kotlin plugin layout,
057            // so the path to Kotlin is specified in a system property
058            String jpsKotlinHome = System.getProperty(JPS_KOTLIN_HOME_PROPERTY);
059            if (jpsKotlinHome != null) {
060                return new KotlinPathsFromHomeDir(new File(jpsKotlinHome));
061            }
062            return new KotlinPathsFromHomeDir(getCompilerPathForJpsPlugin());
063        }
064    
065        @NotNull
066        public static KotlinPaths getKotlinPathsForJpsPluginOrJpsTests() {
067            if ("true".equalsIgnoreCase(System.getProperty("kotlin.jps.tests"))) {
068                return getKotlinPathsForDistDirectory();
069            }
070            return getKotlinPathsForJpsPlugin();
071        }
072    
073        @NotNull
074        public static KotlinPaths getKotlinPathsForCompiler() {
075            if (!getPathUtilJar().isFile()) {
076                // Not running from a jar, i.e. it is it must be a unit test
077                return getKotlinPathsForDistDirectory();
078            }
079            return new KotlinPathsFromHomeDir(getCompilerPathForCompilerJar());
080        }
081    
082        @NotNull
083        public static KotlinPaths getKotlinPathsForDistDirectory() {
084            return new KotlinPathsFromHomeDir(new File("dist", HOME_FOLDER_NAME));
085        }
086    
087        @NotNull
088        private static File getCompilerPathForCompilerJar() {
089            File jar = getPathUtilJar();
090    
091            if (!jar.exists()) return NO_PATH;
092    
093            if (jar.getName().equals("kotlin-compiler.jar")) {
094                File lib = jar.getParentFile();
095                return lib.getParentFile();
096            }
097    
098            return NO_PATH;
099        }
100    
101        @NotNull
102        private static File getCompilerPathForJpsPlugin() {
103            File jar = getPathUtilJar();
104    
105            if (!jar.exists()) return NO_PATH;
106    
107            if (jar.getName().equals("kotlin-jps-plugin.jar")) {
108                File pluginHome = jar.getParentFile().getParentFile().getParentFile();
109                return new File(pluginHome, HOME_FOLDER_NAME);
110            }
111    
112            return NO_PATH;
113        }
114    
115        @NotNull
116        private static File getCompilerPathForIdeaPlugin() {
117            File jar = getPathUtilJar();
118    
119            if (!jar.exists()) return NO_PATH;
120    
121            if (jar.getName().equals("kotlin-plugin.jar")) {
122                File lib = jar.getParentFile();
123                File pluginHome = lib.getParentFile();
124    
125                return new File(pluginHome, HOME_FOLDER_NAME);
126            }
127    
128            return NO_PATH;
129        }
130    
131        @NotNull
132        public static File getPathUtilJar() {
133            return getResourcePathForClass(PathUtil.class);
134        }
135    
136        @NotNull
137        public static File getResourcePathForClass(@NotNull Class aClass) {
138            String resourceRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
139            return new File(resourceRoot).getAbsoluteFile();
140        }
141    
142        @NotNull
143        public static VirtualFile jarFileOrDirectoryToVirtualFile(@NotNull File file) {
144            if (file.exists()) {
145                if (file.isDirectory()) {
146                    return VirtualFileManager.getInstance()
147                            .findFileByUrl("file://" + FileUtil.toSystemIndependentName(file.getAbsolutePath()));
148                }
149                else {
150                    return VirtualFileManager.getInstance().findFileByUrl("jar://" + FileUtil.toSystemIndependentName(file.getAbsolutePath()) + "!/");
151                }
152            }
153            else {
154                throw new IllegalStateException("Path " + file + " does not exist.");
155            }
156        }
157    
158        @NotNull
159        public static List<File> getJdkClassesRoots() {
160            return JavaSdkUtil.getJdkClassesRoots(new File(System.getProperty("java.home")), true);
161        }
162    }