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