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