diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/ZipFileUtil.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/ZipFileUtil.java index a98e963cda2..e87ca9b7140 100644 --- a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/ZipFileUtil.java +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/ZipFileUtil.java @@ -20,19 +20,13 @@ import org.eclipse.core.runtime.CoreException; /** - * Utility class to determine if a file is ZIP archive. + * Utility class for zip files. * * @since 1.11 */ public class ZipFileUtil { - /** - * Determines if the given {@link IFileStore} represents an open ZIP file. - * This can be used to check if operations on a ZIP file should be allowed or handled differently. - * - * @param store The file store to check. - * @return true if the store is an instance of {@link ZipFileStore}, false otherwise. - */ + public static boolean isInsideOpenZipFile(IFileStore store) { return store instanceof ZipFileStore; } @@ -51,6 +45,13 @@ public static boolean isInsideOpenZipFile(URI locationURI) { return isInsideOpenZipFile(store); } + /** + * Determines if the given {@link IFileStore} represents an open ZIP file. + * This can be used to check if operations on a ZIP file should be allowed or handled differently. + * + * @param store The file store to check. + * @return true if the store is an instance of {@link ZipFileStore}, false otherwise. + */ public static boolean isOpenZipFile(IFileStore store) { if (isInsideOpenZipFile(store)) { ZipFileStore zipStore = (ZipFileStore) store; @@ -59,6 +60,9 @@ public static boolean isOpenZipFile(IFileStore store) { return false; } + /** + * @see ZipFileUtil#isOpenZipFile(IFileStore) + */ public static boolean isOpenZipFile(URI locationURI) { IFileStore store; try { diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/zip/ZipFileStore.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/zip/ZipFileStore.java index 832bbf9175c..7bf55c54a76 100644 --- a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/zip/ZipFileStore.java +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/zip/ZipFileStore.java @@ -1,14 +1,15 @@ /******************************************************************************* - * Copyright (c) 2022 IBM Corporation and others. + * Copyright (c) 2024 Vector Informatik GmbH 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/ + * 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 + * Contributors: Vector Informatik GmbH - initial API and implementation *******************************************************************************/ + package org.eclipse.core.internal.filesystem.zip; import java.io.ByteArrayOutputStream; @@ -53,7 +54,19 @@ * @since 1.11 */ public class ZipFileStore extends FileStore { + + /** + * A thread-safe map that associates each zip file's URI with a corresponding {@link ReentrantLock}. + *

+ * This map is used to ensure that each zip file is accessed by only one thread at a time, preventing + * concurrent access issues. The keys in the map are {@link URI} objects representing the zip files, and + * the values are {@link ReentrantLock} objects that are used to control access to the corresponding zip file. + * The map itself is wrapped with {@link Collections#synchronizedMap(Map)} to ensure thread safety + * when accessing the map. + *

+ */ private static final Map uriLockMap = Collections.synchronizedMap(new HashMap<>()); + /** * The path of this store within the zip file. */ @@ -64,9 +77,6 @@ public class ZipFileStore extends FileStore { */ private final IFileStore rootStore; - /** - * Creates a new zip file store. - */ public ZipFileStore(IFileStore rootStore, IPath path) { this.rootStore = rootStore; this.path = path.makeRelative(); @@ -85,7 +95,6 @@ private ZipEntry[] childEntries(IProgressMonitor monitor) throws CoreException { } } - @Override public IFileInfo[] childInfos(int options, IProgressMonitor monitor) throws CoreException { ZipEntry[] entries = childEntries(monitor); @@ -108,16 +117,13 @@ public String[] childNames(int options, IProgressMonitor monitor) throws CoreExc return names; } - /** - * Computes the simple file name for a given zip entry. - */ private static String computeName(ZipEntry entry) { String name = entry.getName(); // removes "/" at the end if (name.endsWith("/")) { //$NON-NLS-1$ name = name.substring(0, name.length() - 1); } - // creates last segment after last / + int lastIndex = name.lastIndexOf('/'); if (lastIndex != -1) { @@ -138,12 +144,6 @@ private IFileInfo convertToIFileInfo(Path zipEntryPath, BasicFileAttributes attr return info; } - /** - * Creates a file info object corresponding to a given zip entry - * - * @param entry the zip entry - * @return The file info for a zip entry - */ private static IFileInfo convertZipEntryToFileInfo(ZipEntry entry) { FileInfo info = new FileInfo(computeName(entry)); if (entry.isDirectory()) { @@ -308,6 +308,9 @@ private String getPluginId() { return FrameworkUtil.getBundle(this.getClass()).getSymbolicName(); } + /** + * Returns the path of this file store. + */ public IPath getPath() { return path; } @@ -424,7 +427,6 @@ public void close() throws IOException { // Write the ByteArrayOutputStream's data to the entry // in the ZIP file Files.write(entryPath, this.toByteArray(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); - } catch (Exception e) { throw new IOException("Failed to integrate data into ZIP file", e); //$NON-NLS-1$ } finally { @@ -499,7 +501,6 @@ public URI toURI() { try { return new URI(scheme, null, pathString, rootStoreQuery, null); } catch (URISyntaxException e) { - // should not happen throw new RuntimeException(e); } } @@ -513,7 +514,7 @@ private URI toNioURI() throws URISyntaxException { return new URI(ret); } - void unlock() throws CoreException { + private void unlock() throws CoreException { try { ReentrantLock lock = getLockForURI(toNioURI()); if (lock.isHeldByCurrentThread()) { diff --git a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/VirtualZipFolder.java b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/VirtualZipFolder.java index ec4c9f52eb7..de73ce40c8f 100644 --- a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/VirtualZipFolder.java +++ b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/VirtualZipFolder.java @@ -1,16 +1,15 @@ /******************************************************************************* - * Copyright (c) 2024 IBM Corporation and others. + * Copyright (c) 2024 Vector Informatik GmbH 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 + * 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 + * Contributors: Vector Informatik GmbH - initial API and implementation *******************************************************************************/ + package org.eclipse.core.internal.resources; import java.net.URISyntaxException; @@ -38,23 +37,15 @@ public VirtualZipFolder(IPath path, Workspace container) { @Override public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException { try { - // Close the current ZIP file ZipFileTransformer.closeZipFile(this); - - // Get the file representing the closed ZIP IFile closedZipFile = this.getParent().getFile(new Path(this.getName())); - - // Copy the closed ZIP file to the destination closedZipFile.copy(destination, updateFlags, monitor); - - // Get the copied ZIP file at the new destination IFile copiedZipFile = ResourcesPlugin.getWorkspace().getRoot().getFile(destination); // If the destination is not a nested ZIP, open the copied ZIP file if (!ZipFileUtil.isInsideOpenZipFile(copiedZipFile.getLocationURI())) { ZipFileTransformer.openZipFile(copiedZipFile, false); } - // Reopen the original ZIP file if (!ZipFileUtil.isInsideOpenZipFile(closedZipFile.getLocationURI())) { ZipFileTransformer.openZipFile(closedZipFile, false); @@ -85,16 +76,9 @@ public void delete(int updateFlags, IProgressMonitor monitor) throws CoreExcepti @Override public void move(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException { try { - // Close the current ZIP file ZipFileTransformer.closeZipFile(this); - - // Get the file representing the closed ZIP IFile closedZipFile = this.getParent().getFile(new Path(this.getName())); - - // Move the closed ZIP file to the destination closedZipFile.move(destination, updateFlags, monitor); - - // Get the moved ZIP file at the new destination IFile movedZipFile = ResourcesPlugin.getWorkspace().getRoot().getFile(destination); // If the destination is not a nested ZIP, open the moved ZIP file diff --git a/runtime/bundles/org.eclipse.core.contenttype/src/org/eclipse/core/runtime/content/ZipFileContentDescriber.java b/runtime/bundles/org.eclipse.core.contenttype/src/org/eclipse/core/runtime/content/ZipFileContentDescriber.java index ed1ef2b556f..ff1e9f88eee 100644 --- a/runtime/bundles/org.eclipse.core.contenttype/src/org/eclipse/core/runtime/content/ZipFileContentDescriber.java +++ b/runtime/bundles/org.eclipse.core.contenttype/src/org/eclipse/core/runtime/content/ZipFileContentDescriber.java @@ -17,7 +17,6 @@ /** * @since 3.10 - * */ public class ZipFileContentDescriber extends TextContentDescriber {