diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/AddEntry.java b/jrmcore/src/main/java/jrm/profile/fix/actions/AddEntry.java index 4d75069f..e002168e 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/AddEntry.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/AddEntry.java @@ -18,9 +18,13 @@ import java.io.File; import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.Collections; +import java.util.Map; import jrm.aui.progress.ProgressHandler; import jrm.compressors.Archive; @@ -378,6 +382,121 @@ private boolean dir2Archive(final Archive dstarchive) return false; } + @Override + public boolean doAction(final Session session, final FileSystem dstfs, final ProgressHandler handler, int i, int max) + { + final var dstpath = dstfs.getPath(entity.getName()); + handler.setProgress(null, null, null, progress(i, max, String.format(session.getMsgs().getString(ADD_ENTRY_ADDING), entity.getName()))); //$NON-NLS-1$ + switch(entry.getParent().getType()) + { + case DIR: + return dir2FS(dstpath); + case FAKE: + return fake2FS(dstpath); + case ZIP: + return zip2FS(dstpath); + default: + return default2FS(session, dstpath); + } + } + + /** + * @param session + * @param dstpath + * @return + */ + private boolean default2FS(final Session session, final Path dstpath) + { + Path srcpath = null; + try(Archive srcarchive = new SevenZipArchive(session, entry.getParent().getFile())) + { + final File srcfile; + if((srcfile=srcarchive.extract(entry.getFile())) != null) + { + final var parentDstPath = dstpath.getParent(); + if(parentDstPath != null) + Files.createDirectories(parentDstPath); + srcpath = srcfile.toPath(); + Files.copy(srcpath, dstpath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + } + catch (IOException e) + { + Log.err(String.format(ADD_FROM_S_AT_S_TO_S_AT_S_FAILED, entry.getParent().getRelFile(), srcpath, parent.container.getFile().getName(), dstpath), e); + } + return false; + } + + /** + * @param dstpath + * @return + */ + private boolean zip2FS(final Path dstpath) + { + Path srcpath = null; + try(final var srcfs = FileSystems.newFileSystem(entry.getParent().getFile().toPath(), Collections.singletonMap("readOnly", true));) + { + final var parentDstPath = dstpath.getParent(); + if(parentDstPath != null) + Files.createDirectories(parentDstPath); + srcpath = srcfs.getPath(entry.getFile()); + Files.copy(srcpath, dstpath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + catch (IOException e) + { + Log.err(String.format(ADD_FROM_S_AT_S_TO_S_AT_S_FAILED, entry.getParent().getRelFile(), srcpath, parent.container.getFile().getName(), dstpath), e); + } + return false; + } + + /** + * @param dstpath + * @return + */ + private boolean fake2FS(final Path dstpath) + { + Path srcpath = null; + try + { + final var parentDstPath = dstpath.getParent(); + if(parentDstPath != null) + Files.createDirectories(parentDstPath); + srcpath = entry.getParent().getFile().getParentFile().toPath().resolve(entry.getFile()); + Files.copy(srcpath, dstpath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + catch (IOException e) + { + Log.err(String.format(ADD_FROM_S_TO_S_AT_S_FAILED, srcpath, parent.container.getFile().getName(), dstpath), e); + } + return false; + } + + /** + * @param dstpath + * @return + */ + private boolean dir2FS(final Path dstpath) + { + Path srcpath = null; + try + { + var parentDstPath = dstpath.getParent(); + if(parentDstPath != null) + Files.createDirectories(parentDstPath); + srcpath = entry.getParent().getFile().toPath().resolve(entry.getFile()); + Files.copy(srcpath, dstpath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + catch (IOException e) + { + Log.err(String.format(ADD_FROM_S_TO_S_AT_S_FAILED, srcpath, parent.container.getFile().getName(), dstpath), e); + } + return false; + } + @Override public String toString() { diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/BackupEntry.java b/jrmcore/src/main/java/jrm/profile/fix/actions/BackupEntry.java index 6b6a581a..a72ec6a6 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/BackupEntry.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/BackupEntry.java @@ -18,7 +18,10 @@ import java.io.File; import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import jrm.aui.progress.ProgressHandler; import jrm.compressors.Archive; @@ -139,4 +142,70 @@ else if(entry.getParent().getType() == Type.SEVENZIP) } return false; } + + @Override + public boolean doAction(final Session session, final FileSystem dstfs, final ProgressHandler handler, int i, int max) + { + final var dstPathCrc = dstfs.getPath(entry.getCrc()+'_'+entry.getSize()); + final Path dstPath; + if(entry.getSha1()!=null) + dstPath = dstfs.getPath(entry.getSha1()); + else if(entry.getMd5()!=null) + dstPath = dstfs.getPath(entry.getMd5()); + else + dstPath = dstfs.getPath(entry.getCrc()+'_'+entry.getSize()); + handler.setProgress(null, null, null, progress(i, max, String.format("Backup of %s", entry.getName()))); //$NON-NLS-1$ + Path srcpath = null; + try + { + final var parent2 = dstPath.getParent(); + if(parent2 != null) + Files.createDirectories(parent2); + if(!dstPath.equals(dstPathCrc) && Files.exists(dstPathCrc)) + Files.delete(dstPathCrc); + if (Files.exists(dstPath)) + return true; + if(entry.getParent().getType() == Type.DIR) + { + srcpath = entry.getParent().getFile().toPath().resolve(entry.getFile()); + Files.copy(srcpath, dstPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + else if(entry.getParent().getType() == Type.FAKE) + { + srcpath = entry.getParent().getFile().getParentFile().toPath().resolve(entry.getFile()); + Files.copy(srcpath, dstPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + else if(entry.getParent().getType() == Type.ZIP) + { + try(final var srcfs = FileSystems.newFileSystem(entry.getParent().getFile().toPath(), (ClassLoader)null);) + { + srcpath = srcfs.getPath(entry.getFile()); + Files.copy(srcpath, dstPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + } + else if(entry.getParent().getType() == Type.SEVENZIP) + { + try(Archive srcarchive = new SevenZipArchive(session, entry.getParent().getFile())) + { + if(srcarchive.extract(entry.getFile()) != null) + { + srcpath = new File(srcarchive.getTempDir(), entry.getFile()).toPath(); + Files.copy(srcpath, dstPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + } + } + } + catch(final Exception e) + { + Log.err(e.getMessage(),e); + Log.err("add from " + entry.getParent().getRelFile() + "@" + srcpath + " to " + parent.container.getFile().getName() + "@" + dstPath + " failed"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + } + return false; + } + + } diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/ContainerAction.java b/jrmcore/src/main/java/jrm/profile/fix/actions/ContainerAction.java index 712d4c43..a80baf21 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/ContainerAction.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/ContainerAction.java @@ -17,6 +17,7 @@ package jrm.profile.fix.actions; import java.io.IOException; +import java.nio.file.FileSystem; import java.nio.file.Path; import java.util.ArrayList; import java.util.Comparator; @@ -226,5 +227,27 @@ protected boolean zosAction(final Session session, final ProgressHandler handler } return true; } + + /** + * @param session + * @param handler + * @param fs + * @return + */ + protected boolean fsAction(final Session session, final ProgressHandler handler, final FileSystem fs) + { + var i = 0; + for (final EntryAction action : entryActions) + { + i++; + if (!action.doAction(session, fs, handler, i, entryActions.size() )) + { + Log.err(()->String.format(ACTION_TO_S_AT_S_FAILED, container.getFile().getName(), action.entry.getRelFile())); + return false; + } + } + return true; + } + } diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/DeleteEntry.java b/jrmcore/src/main/java/jrm/profile/fix/actions/DeleteEntry.java index 214f5074..ae269429 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/DeleteEntry.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/DeleteEntry.java @@ -16,6 +16,7 @@ */ package jrm.profile.fix.actions; +import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.util.stream.Collectors; @@ -50,6 +51,24 @@ public DeleteEntry(final Entry entry) super(entry); } + @Override + public boolean doAction(final Session session, final FileSystem dstfs, final ProgressHandler handler, int i, int max) + { + Path path = null; + try + { + handler.setProgress(null, null, null, progress(i, max, String.format(session.getMsgs().getString(DELETE_ENTRY_DELETING), entry.getRelFile()))); //$NON-NLS-1$ + path = dstfs.getPath(entry.getFile()); + Files.deleteIfExists(path); + return true; + } + catch(final Exception e) + { + Log.err(String.format(DELETE_S_AT_S_FAILED, parent.container.getFile().getName(), path)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + return false; + } + @SuppressWarnings("exports") @Override public boolean doAction(Session session, ZipFile zipf, ZipParameters zipp, ProgressHandler handler, int i, int max) diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/DuplicateEntry.java b/jrmcore/src/main/java/jrm/profile/fix/actions/DuplicateEntry.java index ee1e3891..a3084c1f 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/DuplicateEntry.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/DuplicateEntry.java @@ -17,8 +17,10 @@ package jrm.profile.fix.actions; import java.io.IOException; +import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import jrm.aui.progress.ProgressHandler; import jrm.compressors.Archive; @@ -55,6 +57,28 @@ public DuplicateEntry(final String newname, final Entry entry) this.newname = newname; } + @Override + public boolean doAction(final Session session, final FileSystem fs, final ProgressHandler handler, int i, int max) + { + final var dstpath = fs.getPath(newname); + try + { + handler.setProgress(null, null, null, progress(i, max, String.format(session.getMsgs().getString(DUPLICATE_ENTRY_DUPLICATING), entry.getRelFile(), newname))); //$NON-NLS-1$ + final var srcpath = fs.getPath(entry.getFile()); + final var parent2 = dstpath.getParent(); + if(parent2 != null) + Files.createDirectories(parent2); + Files.copy(srcpath, dstpath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + return true; + } + catch(final Exception e) + { + Log.err(e.getMessage(),e); + Log.err(String.format(DUPLICATE_S_AT_S_TO_S_AT_S_FAILED, parent.container.getFile().getName(), entry.getRelFile(), parent.container.getFile().getName(), newname)); + } + return false; + } + @SuppressWarnings("exports") @Override public boolean doAction(Session session, ZipFile zipf, ZipParameters zipp, ProgressHandler handler, int i, int max) diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/EntryAction.java b/jrmcore/src/main/java/jrm/profile/fix/actions/EntryAction.java index 97a83eec..3c8a7045 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/EntryAction.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/EntryAction.java @@ -87,6 +87,17 @@ protected EntryAction(final Entry entry) @SuppressWarnings("exports") public abstract boolean doAction(final Session session, final ZipFile zipf, final ZipParameters zipp, ProgressHandler handler, int i, int max); + /** + * do action on entry on a {@link FileSystem} + * @param session the current {@link Session} + * @param fs the {@link FileSystem} provided by {@link ContainerAction#doAction(Session, ProgressHandler)} in which we should apply entry action + * @param handler handler the {@link ProgressHandler} to show progression state + * @param i the progression level + * @param max the progression maximum + * @return true if successful, otherwise false + */ + public abstract boolean doAction(final Session session, FileSystem fs, ProgressHandler handler, int i, int max); + public long estimatedSize() { return ESTIMATED_SIZE; diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/OpenContainer.java b/jrmcore/src/main/java/jrm/profile/fix/actions/OpenContainer.java index d038e38c..af386f07 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/OpenContainer.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/OpenContainer.java @@ -18,8 +18,12 @@ import java.io.File; import java.io.IOException; +import java.net.URI; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -28,6 +32,8 @@ import jrm.aui.progress.ProgressHandler; import jrm.compressors.SevenZipArchive; import jrm.compressors.ZipArchive; +import jrm.compressors.ZipLevel; +import jrm.compressors.ZipTempThreshold; import jrm.locale.Messages; import jrm.misc.Log; import jrm.profile.data.Container; @@ -174,15 +180,37 @@ private boolean doActionZipE(final Session session, final ProgressHandler handle */ private boolean doActionZip(final Session session, final ProgressHandler handler) { - try(final var zif = new ZipFile(container.getFile())) + if (!entryActions.isEmpty()) { - return zosAction(session, handler, zif); - } - catch (final Exception e) - { - Log.err(e.getMessage(),e); + if(entryActions.get(0) instanceof RenameEntry) + { + final Map env = new HashMap<>(); + env.put("useTempFile", dataSize > ZipTempThreshold.valueOf(session.getUser().getSettings().getProperty(jrm.misc.SettingsEnum.zip_temp_threshold)).getThreshold()); //$NON-NLS-1$ //$NON-NLS-2$ + env.put("compressionLevel", format == FormatOptions.TZIP ? 1 : ZipLevel.valueOf(session.getUser().getSettings().getProperty(jrm.misc.SettingsEnum.zip_compression_level)).getLevel()); //$NON-NLS-1$ //$NON-NLS-2$ + try (final var fs = FileSystems.newFileSystem(URI.create("jar:" + container.getFile().toURI()), env);) //$NON-NLS-1$ + { + if(!fsAction(session, handler, fs)) + return false; + deleteEmptyFolders(fs.getPath("/")); //$NON-NLS-1$ + return true; + } + catch (final Exception e) + { + Log.err(e.getMessage(),e); + } + + } + else try (final var zif = new ZipFile(container.getFile())) + { + return zosAction(session, handler, zif); + } + catch (final Exception e) + { + Log.err(e.getMessage(), e); + } + return false; } - return false; + return true; } /** diff --git a/jrmcore/src/main/java/jrm/profile/fix/actions/RenameEntry.java b/jrmcore/src/main/java/jrm/profile/fix/actions/RenameEntry.java index 5b7629ae..60e012c9 100644 --- a/jrmcore/src/main/java/jrm/profile/fix/actions/RenameEntry.java +++ b/jrmcore/src/main/java/jrm/profile/fix/actions/RenameEntry.java @@ -16,9 +16,11 @@ */ package jrm.profile.fix.actions; +import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.Optional; import java.util.UUID; import jrm.aui.progress.ProgressHandler; @@ -67,7 +69,6 @@ public RenameEntry(final String newname, final Entry entry) this.newname = newname; } - @SuppressWarnings("exports") @Override public boolean doAction(Session session, ZipFile zipf, ZipParameters zipp, ProgressHandler handler, int i, int max) { @@ -76,10 +77,18 @@ public boolean doAction(Session session, ZipFile zipf, ZipParameters zipp, Progr { handler.setProgress(null, null, null, progress(i, max, String.format(session.getMsgs().getString(RENAME_ENTRY_RENAMING), entry.getRelFile(), newname))); //$NON-NLS-1$ - final var fh = zipf.getFileHeader(entry.getFile()); + final var fh = Optional + .ofNullable(zipf.getFileHeader(ZipTools.toZipEntry(entry.getFile()))) + .orElse(zipf.getFileHeader(entry.getFile())); if(fh != null) { + if(!fh.getFileName().equals(ZipTools.toZipEntry(entry.getFile()))) + System.err.println("%s : selected the wrong FileHeader, should be %s, got %s".formatted(parent.container.getFile().getName(),ZipTools.toZipEntry(entry.getFile()),fh.getFileName())); + if(zipf.getFileHeader(newname)!=null) + System.err.println("%s : can't rename %s to %s because destination already exists".formatted(parent.container.getFile().getName(),entry.getFile(),newname)); zipf.renameFile(fh, newname); + if(!fh.getFileName().equals(newname)) + System.err.println("%s : %s has been renamed to %s instead of %s".formatted(parent.container.getFile().getName(),entry.getFile(), fh.getFileName(),newname)); dstpath = Path.of(newname); final var srcpath = entry.getFile(); entry.rename(newname, PathAbstractor.getRelativePath(session, dstpath).toString()); @@ -87,7 +96,10 @@ public boolean doAction(Session session, ZipFile zipf, ZipParameters zipp, Progr return true; } else + { + System.err.println("%s : can't find %s".formatted(parent.container.getFile().getName(),entry.getFile())); Log.err(String.format(RENAME_S_AT_S_TO_S_AT_S, parent.container.getFile().getName(), entry.getRelFile(), parent.container.getFile().getName(), newname)); + } } catch(final Exception e) { @@ -140,6 +152,33 @@ public boolean doAction(final Session session, final Archive archive, final Prog return false; } + @Override + public boolean doAction(final Session session, final FileSystem fs, final ProgressHandler handler, int i, int max) + { + Path dstpath = null; + try + { + handler.setProgress(null, null, null, progress(i, max, String.format(session.getMsgs().getString(RENAME_ENTRY_RENAMING), entry.getRelFile(), newname))); //$NON-NLS-1$ + final var srcpath = fs.getPath(entry.getFile()); + dstpath = fs.getPath(newname); + if(dstpath!=null) + { + final var parent = dstpath.getParent(); + if(parent != null) + Files.createDirectories(parent); + Files.move(srcpath, dstpath, StandardCopyOption.REPLACE_EXISTING); + entry.rename(dstpath.toString(), PathAbstractor.getRelativePath(session, dstpath).toString()); + } + Log.debug(String.format(RENAME_S_AT_S_TO_S_AT_S, parent.container.getFile().getName(), srcpath, parent.container.getFile().getName(), dstpath)); + return true; + } + catch(final Exception e) + { + Log.err(String.format(RENAME_S_AT_S_TO_S_AT_S, parent.container.getFile().getName(), entry.getRelFile(), parent.container.getFile().getName(), newname)); + } + return false; + } + @Override public String toString() {