diff --git a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java index fa7f53362ee7..72f186746272 100644 --- a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java +++ b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-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. @@ -119,7 +119,7 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { private static String urlToPath(URL url) throws MalformedURLException { try { - return new File(url.toURI()).getPath(); + return new File(url.toURI().getSchemeSpecificPart()).getPath(); } catch (URISyntaxException e) { throw new MalformedURLException(url.toString()); diff --git a/platform/util/src/com/intellij/openapi/application/PathManager.java b/platform/util/src/com/intellij/openapi/application/PathManager.java index 43f11b0f9210..f76b29a37d5b 100644 --- a/platform/util/src/com/intellij/openapi/application/PathManager.java +++ b/platform/util/src/com/intellij/openapi/application/PathManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-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. @@ -321,7 +321,7 @@ public class PathManager { String resultPath = null; String protocol = resourceURL.getProtocol(); if (URLUtil.FILE_PROTOCOL.equals(protocol)) { - String path = resourceURL.getFile(); + String path = URLUtil.urlToFile(resourceURL).getPath(); String testPath = path.replace('\\', '/'); String testResourcePath = resourcePath.replace('\\', '/'); if (StringUtil.endsWithIgnoreCase(testPath, testResourcePath)) { @@ -340,13 +340,7 @@ public class PathManager { return null; } - if (SystemInfo.isWindows && resultPath.startsWith("/")) { - resultPath = resultPath.substring(1); - } - resultPath = StringUtil.trimEnd(resultPath, File.separator); - resultPath = URLUtil.unescapePercentSequences(resultPath); - - return resultPath; + return StringUtil.trimEnd(resultPath, File.separator); } public static void loadProperties() { @@ -555,4 +549,4 @@ public class PathManager { } return false; } -} +} \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/io/URLUtil.java b/platform/util/src/com/intellij/util/io/URLUtil.java index 8135f815b7be..0cbf9c146fb5 100644 --- a/platform/util/src/com/intellij/util/io/URLUtil.java +++ b/platform/util/src/com/intellij/util/io/URLUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-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. @@ -16,7 +16,6 @@ package com.intellij.util.io; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.Base64Converter; @@ -24,11 +23,9 @@ import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.FileNotFoundException; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -97,7 +94,7 @@ public class URLUtil { throw new MalformedURLException(url.getFile()); } - @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") final ZipFile zipFile = new ZipFile(FileUtil.unquote(paths.first)); + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") final ZipFile zipFile = new ZipFile(paths.first); ZipEntry zipEntry = zipFile.getEntry(paths.second); if (zipEntry == null) { zipFile.close(); @@ -118,6 +115,8 @@ public class URLUtil { * Returns a pair of path to a .jar file and entry name inside a .jar, or null if the URL does not contain a separator. *

* E.g. "jar:file:///path/to/jar.jar!/resource.xml" is converted into ["/path/to/jar.jar", "resource.xml"]. + *

+ * Please note that the first part is platform-dependent - see UrlUtilTest.testJarUrlSplitter() for examples. */ @Nullable public static Pair splitJarUrl(@NotNull String url) { @@ -132,18 +131,33 @@ public class URLUtil { } if (jarPath.startsWith(FILE_PROTOCOL)) { - jarPath = jarPath.substring(FILE_PROTOCOL.length()); - if (jarPath.startsWith(SCHEME_SEPARATOR)) { - jarPath = jarPath.substring(SCHEME_SEPARATOR.length()); + try { + jarPath = urlToFile(new URL(jarPath)).getPath().replace('\\', '/'); } - else if (StringUtil.startsWithChar(jarPath, ':')) { - jarPath = jarPath.substring(1); + catch (Exception e) { + jarPath = jarPath.substring(FILE_PROTOCOL.length()); + if (jarPath.startsWith(SCHEME_SEPARATOR)) { + jarPath = jarPath.substring(SCHEME_SEPARATOR.length()); + } + else if (StringUtil.startsWithChar(jarPath, ':')) { + jarPath = jarPath.substring(1); + } } } return Pair.create(jarPath, resourcePath); } + @NotNull + public static File urlToFile(@NotNull URL url) { + try { + return new File(url.toURI().getSchemeSpecificPart()); + } + catch (URISyntaxException e) { + throw new IllegalArgumentException("URL='" + url.toString() + "'", e); + } + } + @NotNull public static String unescapePercentSequences(@NotNull String s) { if (s.indexOf('%') == -1) { @@ -250,6 +264,4 @@ public class URLUtil { } return host; } - - } \ No newline at end of file diff --git a/platform/util/testSrc/com/intellij/openapi/application/PathManagerTest.java b/platform/util/testSrc/com/intellij/openapi/application/PathManagerTest.java index f8245c7c3b93..4c0ec41f92b3 100644 --- a/platform/util/testSrc/com/intellij/openapi/application/PathManagerTest.java +++ b/platform/util/testSrc/com/intellij/openapi/application/PathManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-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. @@ -22,22 +22,35 @@ import org.junit.Test; import java.io.File; import java.util.Random; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; public class PathManagerTest { private static final String TEST_RPOP = "__ij_subst_test__"; private static final String TEST_VALUE = "__" + new Random().nextInt(1000) + "__"; @Before - public void setUp() throws Exception { + public void setUp() { System.setProperty(TEST_RPOP, TEST_VALUE); } @After - public void tearDown() throws Exception { + public void tearDown() { System.clearProperty(TEST_RPOP); } + @Test + public void testResourceRoot() { + String jarRoot = PathManager.getResourceRoot(getClass(), "/" + String.class.getName().replace('.', '/') + ".class"); + assertNotNull(jarRoot); + assertTrue(jarRoot, jarRoot.endsWith(".jar")); + assertTrue(new File(jarRoot).isFile()); + + String dirRoot = PathManager.getResourceRoot(getClass(), "/" + PathManager.class.getName().replace('.', '/') + ".class"); + assertNotNull(dirRoot); + assertFalse(dirRoot, dirRoot.endsWith("/")); + assertTrue(new File(dirRoot).isDirectory()); + } + @Test public void testVarSubstitution() { assertEquals("", PathManager.substituteVars("")); @@ -83,4 +96,4 @@ public class PathManagerTest { assertEquals("//", PathManager.substituteVars("/${unknown_property_ignore_the_error}/")); } -} +} \ No newline at end of file diff --git a/platform/util/testSrc/com/intellij/util/io/UrlUtilTest.java b/platform/util/testSrc/com/intellij/util/io/UrlUtilTest.java index a2d43c0e54c1..fcc4bb59edb9 100644 --- a/platform/util/testSrc/com/intellij/util/io/UrlUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/io/UrlUtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-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. @@ -23,6 +23,7 @@ package com.intellij.util.io; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.CharsetToolkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,6 +49,19 @@ public class UrlUtilTest { assertPair(URLUtil.splitJarUrl("jar:file:/path/to/jar.jar!/resource.xml"), "/path/to/jar.jar", "resource.xml"); assertPair(URLUtil.splitJarUrl("jar:file:///path/to/jar.jar!/resource.xml"), "/path/to/jar.jar", "resource.xml"); + + if (SystemInfo.isWindows) { + assertPair(URLUtil.splitJarUrl("file:/C:/path/to/jar.jar!/resource.xml"), "C:/path/to/jar.jar", "resource.xml"); + assertPair(URLUtil.splitJarUrl("file:////HOST/share/path/to/jar.jar!/resource.xml"), "//HOST/share/path/to/jar.jar", "resource.xml"); + } + else { + assertPair(URLUtil.splitJarUrl("file:/C:/path/to/jar.jar!/resource.xml"), "/C:/path/to/jar.jar", "resource.xml"); + assertPair(URLUtil.splitJarUrl("file:////HOST/share/path/to/jar.jar!/resource.xml"), "/HOST/share/path/to/jar.jar", "resource.xml"); + } + + assertPair(URLUtil.splitJarUrl("file:/path/to/jar%20with%20spaces.jar!/resource.xml"), "/path/to/jar with spaces.jar", "resource.xml"); + + assertPair(URLUtil.splitJarUrl("file:/path/to/jar with spaces.jar!/resource.xml"), "/path/to/jar with spaces.jar", "resource.xml"); } private static void assertPair(@Nullable Pair pair, String expected1, String expected2) { @@ -83,7 +97,7 @@ public class UrlUtilTest { // https://youtrack.jetbrains.com/issue/WEB-14581#comment=27-1014790 assertThat(URLUtil.getBytesFromDataUri("data:text/plain;charset:utf-8;base64,dGVzdA==")).isEqualTo(test); } - + private static void doUrlTest(@NotNull final String line, @Nullable final String expectedUrl) { final Matcher matcher = URLUtil.URL_PATTERN.matcher(line); boolean found = matcher.find();