diff options
author | Stephan Herrmann | 2020-05-23 13:20:46 +0000 |
---|---|---|
committer | Andrey Loskutov | 2020-05-25 19:27:51 +0000 |
commit | 7370ba8eeee34d98b6349ebdbbd663b12ad19d01 (patch) | |
tree | e8fa2698d73ab7d731ac83e07f284b8c2745ac82 | |
parent | 82287a66aaf75e7f3bdf74d92cd30b312946ca34 (diff) | |
download | eclipse.jdt.core-7370ba8eeee34d98b6349ebdbbd663b12ad19d01.tar.gz eclipse.jdt.core-7370ba8eeee34d98b6349ebdbbd663b12ad19d01.tar.xz eclipse.jdt.core-7370ba8eeee34d98b6349ebdbbd663b12ad19d01.zip |
Bug 563501 - ClosedFileSystemException concerning ZipFileSystemI20200526-1800I20200526-0600
containing ct.sym path
Do not hide exceptions on creation of CtSym, and re-create CTSym in case
somebody closed underlined FileSystem.
Change-Id: Iaf066944069e09489bc4d186a3616cae281d5725
4 files changed, 106 insertions, 66 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunBug563501Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunBug563501Tests.java new file mode 100644 index 0000000000..3fd7f1746b --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunBug563501Tests.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2020 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests; + +import org.eclipse.jdt.core.tests.builder.Bug549646Test; +import org.eclipse.jdt.core.tests.compiler.regression.ModuleCompilationTests; +import org.eclipse.jdt.core.tests.model.ModuleBuilderTests; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Runs minimal suite for reproducing bug 563501. + * This is not part of the regular test suite. + */ +public class RunBug563501Tests extends TestCase { + public RunBug563501Tests(String name) { + super(name); + } + public static Test suite() { + org.eclipse.jdt.core.tests.junit.extension.TestCase.TESTS_NAMES = new String[] { + "testCompilerRegression", "testReleaseOption10", "testConvertToModule" + }; + TestSuite suite = new TestSuite(RunBug563501Tests.class.getName()); + suite.addTest(Bug549646Test.suite()); + suite.addTest(ModuleCompilationTests.suite()); + suite.addTest(ModuleBuilderTests.suite()); + return suite; + } +} + diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java index 8a04b703ef..2dc554db41 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java @@ -13,6 +13,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.util; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; import java.nio.file.DirectoryStream; @@ -108,52 +109,42 @@ public class CtSym { */ private final Map<String, Map<String, Path>> allReleasesPaths = new ConcurrentHashMap<>(); - CtSym(Path jdkHome) { + CtSym(Path jdkHome) throws IOException { this.jdkHome = jdkHome; this.ctSymFile = jdkHome.resolve("lib/ct.sym"); //$NON-NLS-1$ - FileSystem fst = null; + init(); + } + + private void init() throws IOException { boolean exists = Files.exists(this.ctSymFile); - if (exists) { - URI uri = URI.create("jar:file:" + this.ctSymFile.toUri().getRawPath()); //$NON-NLS-1$ + if (!exists) { + throw new FileNotFoundException("File " + this.ctSymFile + " does not exist"); //$NON-NLS-1$//$NON-NLS-2$ + } + FileSystem fst = null; + URI uri = URI.create("jar:file:" + this.ctSymFile.toUri().getRawPath()); //$NON-NLS-1$ + try { + fst = FileSystems.getFileSystem(uri); + } catch (Exception fne) { + // Ignore and move on + } + if (fst == null) { try { + fst = FileSystems.newFileSystem(uri, new HashMap<>()); + } catch (FileSystemAlreadyExistsException e) { fst = FileSystems.getFileSystem(uri); - } catch (Exception fne) { - // Ignore and move on - } - if (fst == null) { - try { - fst = FileSystems.newFileSystem(uri, new HashMap<>()); - } catch (FileSystemAlreadyExistsException e) { - fst = FileSystems.getFileSystem(uri); - } catch (IOException e) { - // - } } } this.fs = fst; if (fst == null) { - this.root = null; - this.isJRE12Plus = false; + throw new IOException("Failed to create ct.sym file system for " + this.ctSymFile); //$NON-NLS-1$ } else { - try { - this.root = fst.getPath("/"); //$NON-NLS-1$ - this.isJRE12Plus = isCurrentRelease12plus(); - } catch (IOException e) { - this.root = null; - } + this.root = fst.getPath("/"); //$NON-NLS-1$ + this.isJRE12Plus = isCurrentRelease12plus(); } - } /** - * @return true if ct.sym file exists and can be read - */ - public boolean exists() { - return this.fs != null; - } - - /** - * @return may return null if ct.sym file doesn't exist + * @return never null */ public FileSystem getFs() { return this.fs; @@ -168,7 +159,7 @@ public class CtSym { } /** - * @return may return null if ct.sym file doesn't exist + * @return never null */ public Path getRoot() { return this.root; @@ -180,9 +171,6 @@ public class CtSym { * @return set with all root paths related to given release in ct.sym file */ public List<Path> releaseRoots(String releaseInHex) { - if (!exists()) { - return Collections.emptyList(); - } List<Path> list = this.releaseRootPaths.computeIfAbsent(releaseInHex, x -> { List<Path> rootDirs = new ArrayList<>(); try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root)) { @@ -355,9 +343,6 @@ public class CtSym { } public byte[] getFileBytes(Path path) throws IOException { - if (!exists()) { - return null; - } if (DISABLE_CACHE) { return JRTUtil.safeReadBytes(path); } else { @@ -421,8 +406,6 @@ public class CtSym { sb.append("CtSym ["); //$NON-NLS-1$ sb.append("file="); //$NON-NLS-1$ sb.append(this.ctSymFile); - sb.append(", exists="); //$NON-NLS-1$ - sb.append(this.exists()); sb.append("]"); //$NON-NLS-1$ return sb.toString(); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java index c109246d1a..789ec9e0ff 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2017 IBM Corporation. + * Copyright (c) 2015, 2020 IBM Corporation. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -127,8 +127,23 @@ public class JRTUtil { return system.orElse(null); } - public static CtSym getCtSym(Path jdkHome) { - return ctSymFiles.computeIfAbsent(jdkHome, x -> new CtSym(x)); + public static CtSym getCtSym(Path jdkHome) throws IOException { + CtSym ctSym; + try { + ctSym = ctSymFiles.compute(jdkHome, (Path x, CtSym current) -> { + if (current == null || !current.getFs().isOpen()) { + try { + return new CtSym(x); + } catch (IOException e) { + throw new RuntimeIOException(e); + } + } + return current; + }); + } catch (RuntimeIOException rio) { + throw rio.getCause(); + } + return ctSym; } /** TEST ONLY (use when changing the "modules.to.load" property). */ @@ -246,10 +261,6 @@ class JrtFileSystemWithOlderRelease extends JrtFileSystem { this.fs = null;// reset and proceed, TODO: this is crude and need to be removed. this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase(); this.ctSym = JRTUtil.getCtSym(Paths.get(this.jdkHome)); - - if (!this.ctSym.exists()) { - return; - } this.fs = this.ctSym.getFs(); if (!Files.exists(this.fs.getPath(this.releaseInHex)) || Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$ @@ -304,6 +315,19 @@ class JrtFileSystemWithOlderRelease extends JrtFileSystem { } +final class RuntimeIOException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public RuntimeIOException(IOException cause) { + super(cause); + } + + @Override + public synchronized IOException getCause() { + return (IOException) super.getCause(); + } +} + class JrtFileSystem { private final Map<String, String> packageToModule = new HashMap<String, String>(); @@ -502,19 +526,6 @@ class JrtFileSystem { } } - static final class RuntimeIOException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public RuntimeIOException(IOException cause) { - super(cause); - } - - @Override - public synchronized IOException getCause() { - return (IOException) super.getCause(); - } - } - public ClassFileReader getClassfile(String fileName, String module, Predicate<String> moduleNameFilter) throws IOException, ClassFormatException { ClassFileReader reader = null; if (module == null) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java index 579cf00ba9..8384bf4978 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java @@ -57,7 +57,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { protected Path releasePath; protected Path modulePath; private String modPathString; - final CtSym ctSym; + private CtSym ctSym; @@ -73,7 +73,12 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { this.externalAnnotationPath = externalAnnotationPath.toString(); } this.release = getReleaseOptionFromCompliance(release); - this.ctSym = JRTUtil.getCtSym(Paths.get(this.zipFilename).getParent().getParent()); + try { + this.ctSym = JRTUtil.getCtSym(Paths.get(this.zipFilename).getParent().getParent()); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, ClasspathJrtWithReleaseOption.class, + "Failed to init ct.sym for " + this.zipFilename, e)); //$NON-NLS-1$ + } initialize(); loadModules(); } @@ -102,9 +107,6 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { */ protected void initialize() throws CoreException { this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase(); - if (!this.ctSym.exists()) { - return; - } this.fs = this.ctSym.getFs(); this.releasePath = this.ctSym.getRoot(); Path modPath = this.fs.getPath(this.releaseInHex + (this.ctSym.isJRE12Plus() ? "" : "-modules")); //$NON-NLS-1$ //$NON-NLS-2$ @@ -282,6 +284,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { } finally { // The same file system is also used in JRTUtil, so don't close it here. this.fs = null; + this.ctSym = null; } } |