001    /*
002     * Copyright 2010-2013 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.jet.utils;
018    
019    import com.intellij.openapi.application.ApplicationManager;
020    import com.intellij.openapi.application.PathManager;
021    import com.intellij.openapi.util.SystemInfo;
022    import com.intellij.openapi.util.io.FileUtil;
023    import com.intellij.openapi.vfs.VirtualFile;
024    import com.intellij.openapi.vfs.VirtualFileManager;
025    import org.jetbrains.annotations.NotNull;
026    
027    import java.io.File;
028    
029    public class PathUtil {
030    
031        public static final String JPS_KOTLIN_HOME_PROPERTY = "jps.kotlin.home";
032    
033        public static final String JS_LIB_JAR_NAME = "kotlin-jslib.jar";
034        public static final String JS_LIB_JS_NAME = "kotlin.js";
035        public static final String JDK_ANNOTATIONS_JAR = "kotlin-jdk-annotations.jar";
036        public static final String ANDROID_SDK_ANNOTATIONS_JAR = "kotlin-android-sdk-annotations.jar";
037        public static final String KOTLIN_JAVA_RUNTIME_JAR = "kotlin-runtime.jar";
038        public static final String KOTLIN_JAVA_RUNTIME_SRC_JAR = "kotlin-runtime-sources.jar";
039        public static final String HOME_FOLDER_NAME = "kotlinc";
040    
041        private static final File NO_PATH = new File("<no_path>");
042    
043        private PathUtil() {}
044    
045        @NotNull
046        public static KotlinPaths getKotlinPathsForIdeaPlugin() {
047            return ApplicationManager.getApplication().isUnitTestMode()
048                ? getKotlinPathsForDistDirectory()
049                : new KotlinPathsFromHomeDir(getCompilerPathForIdeaPlugin());
050        }
051    
052        @NotNull
053        public static KotlinPaths getKotlinPathsForJpsPlugin() {
054            // When JPS is run on TeamCity, it can not rely on Kotlin plugin layout,
055            // so the path to Kotlin is specified in a system property
056            String jpsKotlinHome = System.getProperty(JPS_KOTLIN_HOME_PROPERTY);
057            if (jpsKotlinHome != null) {
058                return new KotlinPathsFromHomeDir(new File(jpsKotlinHome));
059            }
060            return new KotlinPathsFromHomeDir(getCompilerPathForJpsPlugin());
061        }
062    
063        @NotNull
064        public static KotlinPaths getKotlinPathsForJpsPluginOrJpsTests() {
065            if ("true".equalsIgnoreCase(System.getProperty("kotlin.jps.tests"))) {
066                return getKotlinPathsForDistDirectory();
067            }
068            return getKotlinPathsForJpsPlugin();
069        }
070    
071        @NotNull
072        public static KotlinPaths getKotlinPathsForCompiler() {
073            if (!getPathUtilJar().isFile()) {
074                // Not running from a jar, i.e. it is it must be a unit test
075                return getKotlinPathsForDistDirectory();
076            }
077            return new KotlinPathsFromHomeDir(getCompilerPathForCompilerJar());
078        }
079    
080        @NotNull
081        public static KotlinPaths getKotlinPathsForDistDirectory() {
082            return new KotlinPathsFromHomeDir(new File("dist", HOME_FOLDER_NAME));
083        }
084    
085        @NotNull
086        private static File getCompilerPathForCompilerJar() {
087            File jar = getPathUtilJar();
088    
089            if (!jar.exists()) return NO_PATH;
090    
091            if (jar.getName().equals("kotlin-compiler.jar")) {
092                File lib = jar.getParentFile();
093                return lib.getParentFile();
094            }
095    
096            return NO_PATH;
097        }
098    
099        @NotNull
100        private static File getCompilerPathForJpsPlugin() {
101            File jar = getPathUtilJar();
102    
103            if (!jar.exists()) return NO_PATH;
104    
105            if (jar.getName().equals("kotlin-jps-plugin.jar")) {
106                File pluginHome = jar.getParentFile().getParentFile().getParentFile();
107                return new File(pluginHome, HOME_FOLDER_NAME);
108            }
109    
110            return NO_PATH;
111        }
112    
113        @NotNull
114        private static File getCompilerPathForIdeaPlugin() {
115            File jar = getPathUtilJar();
116    
117            if (!jar.exists()) return NO_PATH;
118    
119            if (jar.getName().equals("kotlin-plugin.jar")) {
120                File lib = jar.getParentFile();
121                File pluginHome = lib.getParentFile();
122    
123                return new File(pluginHome, HOME_FOLDER_NAME);
124            }
125    
126            return NO_PATH;
127        }
128    
129        private static File getPathUtilJar() {
130            return getJarPathForClass(PathUtil.class);
131        }
132    
133        @NotNull
134        public static File getJarPathForClass(@NotNull Class aClass) {
135            String resourceRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
136            return new File(resourceRoot).getAbsoluteFile();
137        }
138    
139        @NotNull
140        public static VirtualFile jarFileOrDirectoryToVirtualFile(@NotNull File file) {
141            if (file.exists()) {
142                if (file.isDirectory()) {
143                    return VirtualFileManager.getInstance()
144                            .findFileByUrl("file://" + FileUtil.toSystemIndependentName(file.getAbsolutePath()));
145                }
146                else {
147                    return VirtualFileManager.getInstance().findFileByUrl("jar://" + FileUtil.toSystemIndependentName(file.getAbsolutePath()) + "!/");
148                }
149            }
150            else {
151                throw new IllegalStateException("Path " + file + " does not exist.");
152            }
153        }
154    
155        @NotNull
156        public static File findRtJar() {
157            return findRtJar(System.getProperty("java.home"));
158        }
159    
160        private static File findRtJar(String javaHome) {
161            if (SystemInfo.isMac && !SystemInfo.isJavaVersionAtLeast("1.7")) {
162                File classesJar = new File(new File(javaHome).getParentFile(), "Classes/classes.jar");
163                if (classesJar.exists()) {
164                    return classesJar;
165                }
166    
167                throw new IllegalArgumentException("No classes.jar found under " + classesJar.getParent());
168            }
169            else {
170                File rtJar = new File(javaHome, "lib/rt.jar");
171                if (rtJar.exists()) {
172                    return rtJar;
173                }
174    
175                throw new IllegalArgumentException("No rt.jar found under " + rtJar.getParent());
176            }
177        }
178    }