/* * Copyright 2003-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.reloading; import jetbrains.mps.util.ClassPathReader; import jetbrains.mps.util.ClassType; import jetbrains.mps.util.Pair; import jetbrains.mps.util.PathManager; import jetbrains.mps.util.SystemInfo; import jetbrains.mps.util.URLUtil; import jetbrains.mps.vfs.impl.IoFile; import jetbrains.mps.vfs.path.UniPath; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import sun.misc.Launcher; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public final class CommonPaths { private static final Logger LOG = LogManager.getLogger(CommonPaths.class); private static final String REQUESTER_STRING = "Common paths"; private static final ClassPathCachingFacility ourClassPathCachingFacility = ClassPathCachingFacility.getInstance(); //--------paths----------- public static List<String> getMPSPaths(ClassType type) { if (type == ClassType.JDK) { return getJDKPath(); } else if (type == ClassType.JDK_TOOLS) { return getJDK_ToolsPath(); } final CompositeClassPathItem result = new CompositeClassPathItem(); for (String path : new ClassPathReader(PathManager.getHomePath(), Collections.singletonList(type)).read()) { addIfExists(result, path); } if (type == ClassType.ANNOTATIONS) { addAnnotations(result); } else if (type == ClassType.OPENAPI) { addOpenAPIJars(result); } else if (type == ClassType.CORE) { addCoreJars(result); } else if (type == ClassType.EDITOR) { addEditorJars(result); } else if (type == ClassType.IDEA_PLATFORM) { addRepackedIdeaJars(result); } else if (type == ClassType.IDEA) { addIdeaJars(result); } else if (type == ClassType.PLATFORM) { addPlatformJars(result); } else if (type == ClassType.WORKBENCH) { addWorkbenchJars(result); } else if (type == ClassType.TEST) { addTestJars(result); } return itemToPath(result); } public static List<String> getJDKPath() { return itemToPath(getJDKClassPath()); } private static List<String> getJDK_ToolsPath() { String jarLocation = getJarFileLocation("com.sun.jdi.Field"); if (jarLocation != null) { File file = new File(jarLocation); if (file.exists()) { return Collections.singletonList(file.getAbsolutePath()); } } return Collections.emptyList(); } private static String getJarFileLocation(@NotNull String classFQName) { try { Class cls = Class.forName(classFQName); String classFileResourceLocation = "/" + classFQName.replaceAll("\\.", "/") + ".class"; String classFileResourceURL = cls.getResource(classFileResourceLocation).toString(); Pair<String, String> urls = URLUtil.splitJarUrl(classFileResourceURL); if (urls == null) { return null; } return URLDecoder.decode(urls.o1, Charset.defaultCharset().name()).replace('/', File.separatorChar); } catch (ClassNotFoundException | UnsupportedEncodingException e) { LOG.warn("", e); return null; } } public static String getBaseMPSPath() { String classesPath = PathManager.getHomePath() + File.separator + "classes"; if (new File(classesPath).exists()) { return classesPath; } String mpsJarPath = PathManager.getHomePath() + File.separator + "lib" + File.separatorChar + "mps-boot.jar"; if (new File(mpsJarPath).exists()) { return mpsJarPath; } return null; } //------classpaths : JDK-------- private static List<String> getJDKJars() { List<String> result = new ArrayList<String>(); if (SystemInfo.isMac && !SystemInfo.isJavaVersionAtLeast("1.7")) { // in apple jdk's (< jdk7) rt.jar classes contains in classes.jar result.add("classes.jar"); } else { result.add("rt.jar"); } result.add("jsse.jar"); result.add("jce.jar"); result.add("charsets.jar"); return result; } /** * @deprecated Since MPS 3.3 used only inside this class, so should become private. */ @Deprecated public static IClassPathItem getJDKClassPath() { CompositeClassPathItem composite = new CompositeClassPathItem(); for (String s : getJDKJars()) { addJarForName(composite, s); } return composite; } private static void addJarForName(CompositeClassPathItem composite, String name) { RealClassPathItem rtJar = findBootstrapJarByName(name); if (rtJar != null) { composite.add(rtJar); } else { LOG.error("Can't find " + name + ". Make sure you are using JDK 5.0"); } } private static RealClassPathItem findBootstrapJarByName(String name) { for (URL url : Launcher.getBootstrapClassPath().getURLs()) { try { File file = new File(url.toURI()); if (!file.exists()) continue; if (file.getName().equals(name)) { String canonicalPath = file.getCanonicalPath(); return ourClassPathCachingFacility.createFromPath(canonicalPath, REQUESTER_STRING); } } catch (URISyntaxException | IOException e) { LOG.error(null, e); } } return null; } //------classpaths : MPS-------- public static IClassPathItem getMPSClassPath() { CompositeClassPathItem result = new CompositeClassPathItem(); addCoreJars(result); addEditorJars(result); addPlatformJars(result); addIdeaJars(result); addWorkbenchJars(result); addClasses(result); return result; } private static void addAnnotations(CompositeClassPathItem result) { addIfExists(result, "lib/annotations.jar"); } private static void addOpenAPIJars(CompositeClassPathItem result) { addIfExists(result, "lib/mps-openapi.jar"); } private static void addCoreJars(CompositeClassPathItem result) { addIfExists(result, "lib/mps-annotations.jar"); addIfExists(result, "lib/mps-logging.jar"); addIfExists(result, "lib/mps-messaging.jar"); addIfExists(result, "lib/mps-core.jar"); addIfExists(result, "lib/mps-boot-util.jar"); addIfExists(result, "lib/mps-closures.jar"); addIfExists(result, "lib/mps-collections.jar"); addIfExists(result, "lib/mps-tuples.jar"); addIfExists(result, "lib/log4j.jar"); addIfExists(result, "lib/trove4j.jar"); addIfExists(result, "lib/jdom.jar"); addIfExists(result, "lib/ecj-4.6.2.jar"); addIfExists(result, "lib/guava-19.0.jar"); addIfExists(result, "lib/xstream-1.4.8.jar"); addIfExists(result, "lib/diffutils-1.2.1.jar"); addIfExists(result, "lib/asm-all.jar"); } private static void addEditorJars(CompositeClassPathItem result) { addIfExists(result, "lib/mps-editor.jar"); addIfExists(result, "lib/mps-editor-api.jar"); addIfExists(result, "lib/mps-editor-runtime.jar"); } private static void addRepackedIdeaJars(CompositeClassPathItem result) { addIfExists(result, "lib/openapi.jar"); addIfExists(result, "lib/platform.jar"); } private static void addIdeaJars(CompositeClassPathItem result) { addRepackedIdeaJars(result); addIfExists(result, "lib/netty-all-4.1.9.Final.jar"); addIfExists(result, "lib/sanselan-0.98-snapshot.jar"); addIfExists(result, "lib/util.jar"); addIfExists(result, "lib/extensions.jar"); addIfExists(result, "lib/picocontainer.jar"); addIfExists(result, "lib/forms_rt.jar"); } private static void addPlatformJars(CompositeClassPathItem result) { addIfExists(result, "lib/mps-platform.jar"); addIfExists(result, "lib/mps-icons.jar"); } private static void addWorkbenchJars(CompositeClassPathItem result) { addIfExists(result, "lib/mps-workbench.jar"); addIfExists(result, "lib/junit-4.12.jar"); } private static void addTestJars(CompositeClassPathItem result) { addIfExists(result, "lib/mps-test.jar"); addIfExists(result, "lib/mps-environment.jar"); addIfExists(result, "lib/junit-4.12.jar"); } private static void addClasses(final CompositeClassPathItem result) { String homePath = PathManager.getHomePath(); ClassPathReader classPathReader = new ClassPathReader(PathManager.getHomePath(), Arrays.asList(ClassType.values())); classPathReader.read().stream().forEach(param -> { File dir = new File(homePath, param); if (dir.exists()) { result.add(ourClassPathCachingFacility.createFromPath(dir.getAbsolutePath(), REQUESTER_STRING)); } }); } private static void addIfExists(CompositeClassPathItem item, String path) { String dependentPath = UniPath.fromString(path).toSystemPath().toString(); // fixme waiting for Path#resolve method to resolve children in fs for (String basePath : PathManager.getHomePaths()) { UniPath fullPath = UniPath.fromString(basePath + File.separator + dependentPath).toSystemPath(); if (new IoFile(fullPath).exists()) { item.add(ourClassPathCachingFacility.createFromPath(fullPath.toString(), REQUESTER_STRING)); } } } //--------utils----------- private static List<String> itemToPath(IClassPathItem cp) { List<String> result = new ArrayList<String>(); for (IClassPathItem item : cp.flatten()) { if (item instanceof FileClassPathItem) { result.add(((FileClassPathItem) item).getPath()); } else if (item instanceof JarFileClassPathItem) { result.add(((JarFileClassPathItem) item).getFile().getAbsolutePath()); } else { throw new IllegalArgumentException(item.getClass().getName()); } } return result; } }