From 287eda36dadd33c600d9f62cd2917e2de0b2dce0 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Sun, 5 Oct 2025 12:52:15 -0700 Subject: [PATCH 01/15] Checkpoint FileLike migration --- .../api/assay/AbstractAssayProvider.java | 31 ++++++++++-------- .../assay/AbstractTempDirDataCollector.java | 32 +------------------ .../labkey/api/assay/AssayDataCollector.java | 2 +- .../org/labkey/api/assay/AssayFileWriter.java | 4 +-- .../org/labkey/api/assay/AssayProvider.java | 14 +------- .../api/assay/FileUploadDataCollector.java | 13 ++++---- .../api/assay/PipelineDataCollector.java | 7 ++-- .../PreviouslyUploadedDataCollector.java | 11 +++---- .../api/assay/actions/AssayRunUploadForm.java | 4 +-- api/src/org/labkey/api/assay/fileUpload.jsp | 3 +- .../labkey/assay/TextAreaDataCollector.java | 15 +-------- .../org/labkey/assay/TsvAssayProvider.java | 4 +-- .../src/org/labkey/assay/view/dataUpload.jsp | 2 +- 13 files changed, 44 insertions(+), 98 deletions(-) diff --git a/api/src/org/labkey/api/assay/AbstractAssayProvider.java b/api/src/org/labkey/api/assay/AbstractAssayProvider.java index 6a6c72f562b..bf070724392 100644 --- a/api/src/org/labkey/api/assay/AbstractAssayProvider.java +++ b/api/src/org/labkey/api/assay/AbstractAssayProvider.java @@ -115,6 +115,7 @@ import org.labkey.api.view.NavTree; import org.labkey.api.view.NotFoundException; import org.labkey.api.view.ViewContext; +import org.labkey.vfs.FileLike; import org.labkey.vfs.FileSystemLike; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; @@ -612,7 +613,7 @@ public List>> createDefaultDomains(Cont } @Override - public List getDataCollectors(@Nullable Map uploadedFiles, AssayRunUploadForm context) + public List getDataCollectors(@Nullable Map uploadedFiles, AssayRunUploadForm context) { return getDataCollectors(uploadedFiles, context, true); } @@ -623,7 +624,7 @@ public String getResourceName() return getName(); } - public List getDataCollectors(@Nullable Map uploadedFiles, AssayRunUploadForm context, boolean allowFileReuseOnReRun) + public List getDataCollectors(@Nullable Map uploadedFiles, AssayRunUploadForm context, boolean allowFileReuseOnReRun) { List result = new ArrayList<>(); if (!PipelineDataCollector.getFileQueue(context).isEmpty()) @@ -636,7 +637,8 @@ public List getDataCollectors(@Nullable Map up { // In the re-run scenario, figure out what files to offer up for reuse - Map reusableFiles = new HashMap<>(); +// Map reusableFiles = new HashMap<>(); + Map reusableFiles = new HashMap<>(); // Include any files that were uploaded as part of this request if (uploadedFiles != null && !uploadedFiles.isEmpty()) { @@ -674,14 +676,15 @@ else if (inputDatas.size() > 1) // Filter out any files that aren't under the current pipeline root, since we won't be able to resolve // them successfully due to security restrictions for what's an allowable input to the new run. See issue 18387. PipeRoot pipeRoot = PipelineService.get().findPipelineRoot(context.getContainer()); - for (Iterator> iter = reusableFiles.entrySet().iterator(); iter.hasNext(); ) + for (Iterator> iter = reusableFiles.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry entry = iter.next(); + Map.Entry entry = iter.next(); // If it's not under the current pipeline root - if (pipeRoot == null || !pipeRoot.isUnderRoot(entry.getValue())) + if (pipeRoot == null || !pipeRoot.isUnderRoot(entry.getValue().toNioPathForRead())) { - // Remove it from the collection + // Remove it from both collections iter.remove(); + reusableFiles.remove(entry.getKey()); } } @@ -691,8 +694,7 @@ else if (inputDatas.size() > 1) // to reuse or re-upload if (!reusableFiles.isEmpty()) { - var reusableFileLike = FileSystemLike.wrapFiles(reusableFiles); - result.add(new PreviouslyUploadedDataCollector<>(reusableFileLike)); + result.add(new PreviouslyUploadedDataCollector<>(reusableFiles)); } result.add(new FileUploadDataCollector<>(getMaxFileInputs())); } @@ -708,8 +710,7 @@ else if (inputDatas.size() > 1) // Normal (non-rerun) scenario if (uploadedFiles != null) { - var uploadedFileLikes = FileSystemLike.wrapFiles(uploadedFiles); - result.add(new PreviouslyUploadedDataCollector<>(uploadedFileLikes)); + result.add(new PreviouslyUploadedDataCollector<>(uploadedFiles)); } result.add(new FileUploadDataCollector<>(getMaxFileInputs())); } @@ -717,12 +718,14 @@ else if (inputDatas.size() > 1) return result; } - private void addReusableData(Map reusableFiles, ExpData inputData) + private void addReusableData(Map reusableFiles, ExpData inputData) { // Not all datas are associated with a file if (inputData.getFile() != null) { - reusableFiles.put(AssayDataCollector.PRIMARY_FILE + (reusableFiles.isEmpty() ? "" : Integer.toString(reusableFiles.size())), inputData.getFile()); + String key = AssayDataCollector.PRIMARY_FILE + (reusableFiles.isEmpty() ? "" : Integer.toString(reusableFiles.size())); + File f = inputData.getFile(); + reusableFiles.put(key, org.labkey.vfs.FileSystemLike.wrapFile(f)); } } @@ -733,7 +736,7 @@ public AssayRunCreator getRunCreator() } @Override - public ExpProtocol createAssayDefinition(User user, Container container, String name, String description, ExpProtocol.Status status, XarContext context) + public ExpProtocol createAssayDefinition(User user, Container container, String name, String description, ExpProtocol.Status status, @NotNull XarContext context) throws ExperimentException { String protocolLsid = getAssayProtocolLsid(container, name, context); diff --git a/api/src/org/labkey/api/assay/AbstractTempDirDataCollector.java b/api/src/org/labkey/api/assay/AbstractTempDirDataCollector.java index 904bdfea196..cca1e9fd544 100644 --- a/api/src/org/labkey/api/assay/AbstractTempDirDataCollector.java +++ b/api/src/org/labkey/api/assay/AbstractTempDirDataCollector.java @@ -47,31 +47,7 @@ public abstract class AbstractTempDirDataCollector) context).getUploadAttemptID(); - - // Cleanup files other than input generated by transform scripts - FileLike tempDir = ensureSubdirectory(context.getContainer(), TEMP_DIR_NAME); - FileLike uploadAttemptDir = tempDir.resolveChild(uploadAttemptID); - if (NetworkDrive.exists(uploadAttemptDir)) - { - try - { - FileUtils.deleteDirectory(uploadAttemptDir.toNioPathForWrite().toFile()); - } - catch (IOException e) - { - // Delete quietly - } - } - } - + @Override public void initDir(ContextType context) throws ExperimentException { @@ -234,12 +210,6 @@ public Map uploadComplete(ContextType context, @Nullable ExpRu return result; } - /** @return the preferred name for the run given the primary data file */ - protected String getPreferredAssayId(File primaryFile) - { - return primaryFile.getName(); - } - protected String getPreferredAssayId(FileLike primaryFile) { return primaryFile.getName(); diff --git a/api/src/org/labkey/api/assay/AssayDataCollector.java b/api/src/org/labkey/api/assay/AssayDataCollector.java index d713cc9cf10..36774c90c65 100644 --- a/api/src/org/labkey/api/assay/AssayDataCollector.java +++ b/api/src/org/labkey/api/assay/AssayDataCollector.java @@ -57,7 +57,7 @@ public String getButtonText() } /** @return the UI to plug into the import wizard for the user to somehow select/upload the file */ - HttpView getView(ContextType context) throws ExperimentException; + HttpView getView(ContextType context) throws ExperimentException; /** @return the name for this AssayDataCollector. Needs to be unique within the set of data collectors for any given import attempt */ String getShortName(); diff --git a/api/src/org/labkey/api/assay/AssayFileWriter.java b/api/src/org/labkey/api/assay/AssayFileWriter.java index 327151f9b62..d2130887aaa 100644 --- a/api/src/org/labkey/api/assay/AssayFileWriter.java +++ b/api/src/org/labkey/api/assay/AssayFileWriter.java @@ -232,7 +232,7 @@ public String getFileName(MultipartFile file) return file.getOriginalFilename(); } - public Map savePostedFiles(ContextType context, Set parameterNames, boolean allowMultiple, boolean ensureExpData) throws ExperimentException, IOException + public Map savePostedFiles(ContextType context, @NotNull Set parameterNames, boolean allowMultiple, boolean ensureExpData) throws ExperimentException, IOException { Map files = CollectionUtils.enforceValueClass(new TreeMap<>(), FileLike.class); Set originalFileNames = new HashSet<>(); @@ -244,7 +244,7 @@ public Map savePostedFiles(ContextType context, Set pa while (iter.hasNext()) { Map.Entry> entry = iter.next(); - if (parameterNames == null || parameterNames.contains(entry.getKey())) + if (parameterNames.contains(entry.getKey())) { List multipartFiles = entry.getValue(); boolean isAfterFirstFile = false; diff --git a/api/src/org/labkey/api/assay/AssayProvider.java b/api/src/org/labkey/api/assay/AssayProvider.java index 1e8dd43ecd3..d94874809db 100644 --- a/api/src/org/labkey/api/assay/AssayProvider.java +++ b/api/src/org/labkey/api/assay/AssayProvider.java @@ -59,10 +59,8 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; -import java.io.File; import java.io.IOException; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -116,17 +114,7 @@ enum ReRunSupport AssayRunCreator getRunCreator(); /** @return all the legal data collectors that the user can choose from for the current import attempt */ - // TODO File->FileLike - List getDataCollectors(Map uploadedFiles, AssayRunUploadForm context); - - default List getDataCollectorsFileObject(Map uploadedFileObjects, AssayRunUploadForm context) - { - Map map = new HashMap<>(); - if (uploadedFileObjects != null) - for (var entry : uploadedFileObjects.entrySet()) - map.put(entry.getKey(), entry.getValue().toNioPathForRead().toFile()); - return getDataCollectors(map, context); - } + List getDataCollectors(Map uploadedFileObjects, AssayRunUploadForm context); /** * @return the name of the assay provider. diff --git a/api/src/org/labkey/api/assay/FileUploadDataCollector.java b/api/src/org/labkey/api/assay/FileUploadDataCollector.java index 2f018065ee8..98551e1df12 100644 --- a/api/src/org/labkey/api/assay/FileUploadDataCollector.java +++ b/api/src/org/labkey/api/assay/FileUploadDataCollector.java @@ -23,7 +23,6 @@ import org.labkey.api.view.JspView; import org.labkey.vfs.FileLike; -import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.HashMap; @@ -38,7 +37,7 @@ public class FileUploadDataCollector> extends AbstractTempDirDataCollector { private final int _maxFileInputs; - private final Map _reusableFiles; + private final Map _reusableFiles; // Name of the form for the file. private final String _fileInputName; @@ -52,12 +51,12 @@ public FileUploadDataCollector(int maxFileInputs) this(maxFileInputs, Collections.emptyMap()); } - public FileUploadDataCollector(int maxFileInputs, Map reusableFiles) + public FileUploadDataCollector(int maxFileInputs, Map reusableFiles) { this(maxFileInputs, reusableFiles, PRIMARY_FILE); } - public FileUploadDataCollector(int maxFileInputs, Map reusableFiles, String fileInputName) + public FileUploadDataCollector(int maxFileInputs, Map reusableFiles, String fileInputName) { _maxFileInputs = maxFileInputs; _reusableFiles = Collections.unmodifiableMap(reusableFiles); @@ -69,12 +68,12 @@ public FileUploadDataCollector(int maxFileInputs, Map reusableFile } @Override - public HttpView getView(ContextType context) + public HttpView getView(ContextType context) { - return new JspView("/org/labkey/api/assay/fileUpload.jsp", this); + return new JspView<>("/org/labkey/api/assay/fileUpload.jsp", this); } - public Map getReusableFiles() + public Map getReusableFiles() { return _reusableFiles; } diff --git a/api/src/org/labkey/api/assay/PipelineDataCollector.java b/api/src/org/labkey/api/assay/PipelineDataCollector.java index b484d562181..1db558acd23 100644 --- a/api/src/org/labkey/api/assay/PipelineDataCollector.java +++ b/api/src/org/labkey/api/assay/PipelineDataCollector.java @@ -22,6 +22,7 @@ import org.labkey.api.exp.ExperimentException; import org.labkey.api.exp.api.ExpProtocol; import org.labkey.api.exp.api.ExpRun; +import org.labkey.api.util.DOM; import org.labkey.api.util.HtmlString; import org.labkey.api.util.HtmlStringBuilder; import org.labkey.api.util.Pair; @@ -41,8 +42,6 @@ import java.util.List; import java.util.Map; -import static org.labkey.api.util.HtmlString.unsafe; - /** * Data collector that supplies files the user previously selected through the pipeline/file browser. * @@ -58,7 +57,7 @@ public PipelineDataCollector() private File _originalFileLocation = null; @Override - public HttpView getView(ContextType context) throws ExperimentException + public HttpView getView(ContextType context) throws ExperimentException { return new HtmlView(getHTML(context)); } @@ -68,7 +67,7 @@ public HtmlString getHTML(ContextType context) Map files = getCurrentFilesForDisplay(context); if (files.isEmpty()) { - return unsafe("
No files have been selected.
"); + return DOM.createHtml(DOM.DIV(DOM.at(DOM.cl("labkey-error")), "No files have been selected.")); } HtmlStringBuilder html = HtmlStringBuilder.of(); diff --git a/api/src/org/labkey/api/assay/PreviouslyUploadedDataCollector.java b/api/src/org/labkey/api/assay/PreviouslyUploadedDataCollector.java index 11588d03805..293b90fb64b 100644 --- a/api/src/org/labkey/api/assay/PreviouslyUploadedDataCollector.java +++ b/api/src/org/labkey/api/assay/PreviouslyUploadedDataCollector.java @@ -16,7 +16,7 @@ package org.labkey.api.assay; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Strings; import org.jetbrains.annotations.NotNull; import org.labkey.api.collections.CollectionUtils; import org.labkey.api.data.Container; @@ -27,7 +27,6 @@ import org.labkey.api.view.InsertView; import org.labkey.vfs.FileLike; -import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.LinkedHashMap; @@ -100,19 +99,19 @@ public HtmlView getView(ContextType context) sb.append(separator); separator = ", "; sb.append(entry.getValue().getName()); - sb.append(getHiddenFormElementHTML(context.getContainer(), entry.getKey(), entry.getValue().toNioPathForRead().toFile())); + sb.append(getHiddenFormElementHTML(context.getContainer(), entry.getKey(), entry.getValue())); } return new HtmlView(sb); } - public HtmlString getHiddenFormElementHTML(Container container, String formElementName, File file) + public HtmlString getHiddenFormElementHTML(Container container, String formElementName, FileLike file) { PipeRoot pipeRoot = getPipelineRoot(container); HtmlStringBuilder sb = HtmlStringBuilder.of(); sb.unsafeAppend(" getFilesFromRequest(ContextType context, Type type Map result = CollectionUtils.enforceValueClass(new LinkedHashMap<>(), FileLike.class); for (int i = 0; i < paths.length; i++) { - result.put(names[i], pipelineRoot.resolvePathToFileLike(StringUtils.replace(paths[i],"\\","/"))); + result.put(names[i], pipelineRoot.resolvePathToFileLike(Strings.CS.replace(paths[i],"\\","/"))); } return result; } diff --git a/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java b/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java index 534f7193b44..88caae0db1d 100644 --- a/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java +++ b/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java @@ -356,14 +356,14 @@ public Map getAdditionalPostedFiles(List <%@ page import="java.util.Collections" %> <%@ page import="java.util.Map" %> +<%@ page import="org.labkey.vfs.FileLike" %> <%@ page extends="org.labkey.api.jsp.JspBase" %> <%@ taglib prefix="labkey" uri="http://www.labkey.org/taglib" %> <%! @@ -99,7 +100,7 @@ // Add an entry for all file groups that can be reused from a previous upload <% PreviouslyUploadedDataCollector reuseDataCollector = new PreviouslyUploadedDataCollector(Collections.emptyMap(), PreviouslyUploadedDataCollector.Type.ReRun); - for (Map.Entry entry : bean.getReusableFiles().entrySet()) { %> + for (Map.Entry entry : bean.getReusableFiles().entrySet()) { %> addFileUploadInputRow(null, <%= q(entry.getValue().getName())%>, <%= q(reuseDataCollector.getHiddenFormElementHTML(getContainer(), entry.getKey(), entry.getValue()))%>); <% } %> diff --git a/assay/src/org/labkey/assay/TextAreaDataCollector.java b/assay/src/org/labkey/assay/TextAreaDataCollector.java index 78e4f0ce6d0..2e3eff2528d 100644 --- a/assay/src/org/labkey/assay/TextAreaDataCollector.java +++ b/assay/src/org/labkey/assay/TextAreaDataCollector.java @@ -27,7 +27,6 @@ import org.labkey.vfs.FileLike; import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Map; @@ -41,7 +40,7 @@ public class TextAreaDataCollector\n" + "