From c0feb67504a7c1fff817f056d556d49258ba774b Mon Sep 17 00:00:00 2001 From: ian Date: Fri, 21 Mar 2025 16:25:39 -0700 Subject: [PATCH 1/5] Convert File usages to use FileLike or the comparable class --- flow/src/org/labkey/flow/controllers/FlowController.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/flow/src/org/labkey/flow/controllers/FlowController.java b/flow/src/org/labkey/flow/controllers/FlowController.java index 7efdbe4c2d..afebf6cb97 100644 --- a/flow/src/org/labkey/flow/controllers/FlowController.java +++ b/flow/src/org/labkey/flow/controllers/FlowController.java @@ -41,6 +41,7 @@ import org.labkey.api.security.permissions.ReadPermission; import org.labkey.api.settings.AdminConsole; import org.labkey.api.settings.AdminConsole.SettingsLinkType; +import org.labkey.api.util.FileUtil; import org.labkey.api.util.JobRunner; import org.labkey.api.util.TestContext; import org.labkey.api.view.ActionURL; @@ -64,11 +65,12 @@ import org.labkey.flow.query.FlowSchema; import org.labkey.flow.webparts.FlowFolderType; import org.labkey.flow.webparts.OverviewWebPart; +import org.labkey.vfs.FileLike; +import org.labkey.vfs.FileSystemLike; import org.springframework.validation.BindException; import org.springframework.validation.Errors; import org.springframework.web.servlet.ModelAndView; -import java.io.File; import java.net.URI; @Marshal(Marshaller.Jackson) @@ -312,7 +314,9 @@ public boolean handlePost(FlowAdminForm form, BindException errors) { if (form.getWorkingDirectory() != null) { - File dir = new File(form.getWorkingDirectory()); + FileLike dir = new FileSystemLike.Builder(FileUtil.stringToPath(getContainer(), form.getWorkingDirectory())) + .readonly().root(); + if (!dir.exists()) { errors.rejectValue("workingDirectory", ERROR_MSG, "Path does not exist: " + form.getWorkingDirectory()); From 143da8a6335c61a9f5245aa71ff54e4df1c6c3f9 Mon Sep 17 00:00:00 2001 From: ian Date: Thu, 27 Mar 2025 15:24:45 -0700 Subject: [PATCH 2/5] Fix run paths --- flow/src/org/labkey/flow/controllers/FlowController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flow/src/org/labkey/flow/controllers/FlowController.java b/flow/src/org/labkey/flow/controllers/FlowController.java index afebf6cb97..627517bb4f 100644 --- a/flow/src/org/labkey/flow/controllers/FlowController.java +++ b/flow/src/org/labkey/flow/controllers/FlowController.java @@ -28,6 +28,7 @@ import org.labkey.api.data.ContainerManager; import org.labkey.api.data.DataRegion; import org.labkey.api.module.Module; +import org.labkey.api.pipeline.PipelineService; import org.labkey.api.portal.ProjectUrls; import org.labkey.api.query.QueryDefinition; import org.labkey.api.query.QueryParseException; @@ -312,7 +313,7 @@ public ModelAndView getView(FlowAdminForm form, boolean reshow, BindException er @Override public boolean handlePost(FlowAdminForm form, BindException errors) { - if (form.getWorkingDirectory() != null) + if (form.getWorkingDirectory() != null && PipelineService.get().findPipelineRoot(getContainer()).getRootFileLike().isDescendant(FileUtil.createUri(form.getWorkingDirectory()) )) { FileLike dir = new FileSystemLike.Builder(FileUtil.stringToPath(getContainer(), form.getWorkingDirectory())) .readonly().root(); From 6c204683e64feabeba66c156385c7ca228cf5f67 Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 15 Apr 2025 15:16:33 -0700 Subject: [PATCH 3/5] Fix flow import path resolution --- .../executescript/AnalysisScriptController.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java b/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java index 6b7366df1b..d673ceb42c 100644 --- a/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java +++ b/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java @@ -85,6 +85,7 @@ import org.labkey.flow.script.WorkspaceJob; import org.labkey.flow.util.SampleUtil; import org.labkey.vfs.FileLike; +import org.labkey.vfs.FileSystemLike; import org.springframework.validation.BindException; import org.springframework.validation.Errors; import org.springframework.web.multipart.MultipartFile; @@ -910,7 +911,6 @@ private RunType hasExistingRuns(File workspaceFile) return rt; } - private void stepSelectAnalysis(ImportAnalysisForm form, BindException errors) { WorkspaceData workspaceData = form.getWorkspace(); @@ -922,18 +922,14 @@ private void stepSelectAnalysis(ImportAnalysisForm form, BindException errors) return; } - PipeRoot root = null; + PipeRoot root = getPipeRoot(); String path = workspaceData.getPath(); - File workspaceFile = null; - if (path != null) - { - root = getPipeRoot(); - workspaceFile = root.resolvePath(path); - } + FileLike workspaceFL = root.resolvePathToFileLike(path); RunType rt = RunType.None; - if (workspaceFile != null && form.getSelectFCSFilesOption() == null && form.getKeywordDir() == null) + if (workspaceFL != null && form.getSelectFCSFilesOption() == null && form.getKeywordDir() == null) { + File workspaceFile = FileSystemLike.toFile(workspaceFL); rt = hasExistingRuns(workspaceFile); if (rt != RunType.None) { @@ -945,9 +941,10 @@ private void stepSelectAnalysis(ImportAnalysisForm form, BindException errors) { // Next, guess the FCS files are in the same directory as the workspace, but not analyzed yet. File keywordDir = null; + File sampleDir = workspaceFile.getParentFile(); for (ISampleInfo sampleInfo : samples) { - File sampleFile = FileUtil.appendName(new File(workspaceFile.getParent()),sampleInfo.getLabel()); + File sampleFile = FileUtil.appendName(sampleDir, sampleInfo.getLabel()); if (sampleFile.exists()) { keywordDir = workspaceFile.getParentFile(); From e250c8b5da503923961b3932725486b217ad35be Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 15 Apr 2025 16:50:50 -0700 Subject: [PATCH 4/5] return null check --- .../controllers/executescript/AnalysisScriptController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java b/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java index d673ceb42c..1fa1721961 100644 --- a/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java +++ b/flow/src/org/labkey/flow/controllers/executescript/AnalysisScriptController.java @@ -924,7 +924,7 @@ private void stepSelectAnalysis(ImportAnalysisForm form, BindException errors) PipeRoot root = getPipeRoot(); String path = workspaceData.getPath(); - FileLike workspaceFL = root.resolvePathToFileLike(path); + FileLike workspaceFL = path != null ? root.resolvePathToFileLike(path) : null; RunType rt = RunType.None; if (workspaceFL != null && form.getSelectFCSFilesOption() == null && form.getKeywordDir() == null) From 58ff7bef3973262d74d4e59ec246607068505740 Mon Sep 17 00:00:00 2001 From: ian Date: Wed, 16 Apr 2025 17:04:02 -0700 Subject: [PATCH 5/5] Adjust FlowSettings to at least partially use FileLike Fix lint in FlowCompensationMatrix --- flow/src/org/labkey/flow/FlowSettings.java | 30 +++++++++--- .../flow/controllers/FlowController.java | 13 +++-- .../flow/data/FlowCompensationMatrix.java | 49 ++++++++++--------- 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/flow/src/org/labkey/flow/FlowSettings.java b/flow/src/org/labkey/flow/FlowSettings.java index 7a8943d446..cf71979bf0 100644 --- a/flow/src/org/labkey/flow/FlowSettings.java +++ b/flow/src/org/labkey/flow/FlowSettings.java @@ -22,6 +22,8 @@ import org.labkey.api.data.PropertyManager; import org.labkey.api.data.PropertyManager.WritablePropertyMap; import org.labkey.api.util.FileUtil; +import org.labkey.vfs.FileLike; +import org.labkey.vfs.FileSystemLike; import java.io.File; import java.io.IOException; @@ -29,24 +31,25 @@ public class FlowSettings { - static private File _tempAnalysisDirectory; + static private FileLike _tempAnalysisDirectory; static private final String PROPCAT_FLOW = "flow"; static private final String PROPNAME_WORKINGDIRECTORY = "workingDirectory"; static private final String PROPNAME_DELETE_FILES = "deleteFiles"; - static private File getTempAnalysisDirectory() + static private FileLike getTempAnalysisDirectory() { if (_tempAnalysisDirectory != null) return _tempAnalysisDirectory; - File file; try { - file = FileUtil.createTempFile("FlowAnalysis", "tmp"); - File ret = new File(file.getParentFile(), "FlowAnalysis"); + FileLike ret = FileUtil.createTempDirectoryFileLike("FlowAnalysis"); + FileLike file = ret.resolveChild("FlowAnalysis.tmp"); if (!ret.exists()) { FileUtil.mkdir(ret); } + + // Clean-up any existing prior analysis file file.delete(); _tempAnalysisDirectory = ret; return ret; @@ -57,12 +60,21 @@ static private File getTempAnalysisDirectory() } } + /** + * Get the flow analysis working directory. + * Note: This may be outside the FileLike/FileSystemLike paradigm, it is either a temp directory or a value set by the admins + * + * @return File object representing the Flow analysis working directory. + */ static public File getWorkingDirectory() { + //Get admin provided setting if it exists String path = getWorkingDirectoryPath(); if (path != null) return new File(path); - return getTempAnalysisDirectory(); + + // Otherwise default to the + return FileSystemLike.toFile(getTempAnalysisDirectory()); } static public String getWorkingDirectoryPath() @@ -72,6 +84,12 @@ static public String getWorkingDirectoryPath() return map.get(PROPNAME_WORKINGDIRECTORY); } + /** + * Save the Flow Analysis working directory path setting + * Note: This may be outside the FileLike/FileSystemLike paradigm + * + * @param path string file path to the flow analysis working directory + */ static public void setWorkingDirectoryPath(String path) { Container container = ContainerManager.getRoot(); diff --git a/flow/src/org/labkey/flow/controllers/FlowController.java b/flow/src/org/labkey/flow/controllers/FlowController.java index 627517bb4f..163baf5bbb 100644 --- a/flow/src/org/labkey/flow/controllers/FlowController.java +++ b/flow/src/org/labkey/flow/controllers/FlowController.java @@ -28,6 +28,7 @@ import org.labkey.api.data.ContainerManager; import org.labkey.api.data.DataRegion; import org.labkey.api.module.Module; +import org.labkey.api.pipeline.PipeRoot; import org.labkey.api.pipeline.PipelineService; import org.labkey.api.portal.ProjectUrls; import org.labkey.api.query.QueryDefinition; @@ -301,6 +302,9 @@ public class FlowAdminAction extends FormViewAction @Override public void validateCommand(FlowAdminForm form, Errors errors) { + PipeRoot root = PipelineService.get().findPipelineRoot(getContainer()); + if (root == null) + errors.rejectValue("root", ERROR_MSG, "Pipeline root not found for the current container."); } @Override @@ -313,12 +317,13 @@ public ModelAndView getView(FlowAdminForm form, boolean reshow, BindException er @Override public boolean handlePost(FlowAdminForm form, BindException errors) { - if (form.getWorkingDirectory() != null && PipelineService.get().findPipelineRoot(getContainer()).getRootFileLike().isDescendant(FileUtil.createUri(form.getWorkingDirectory()) )) + PipeRoot root = PipelineService.get().findPipelineRoot(getContainer()); + + if (form.getWorkingDirectory() != null && root.getRootFileLike().isDescendant(FileUtil.createUri(form.getWorkingDirectory()))) { - FileLike dir = new FileSystemLike.Builder(FileUtil.stringToPath(getContainer(), form.getWorkingDirectory())) - .readonly().root(); + FileLike dir = root.resolvePathToFileLike(form.getWorkingDirectory()); - if (!dir.exists()) + if (dir == null || !dir.exists()) { errors.rejectValue("workingDirectory", ERROR_MSG, "Path does not exist: " + form.getWorkingDirectory()); return false; diff --git a/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java b/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java index 8efd6bf2f2..0d552d852e 100644 --- a/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java +++ b/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java @@ -25,6 +25,7 @@ import org.labkey.api.query.FieldKey; import org.labkey.api.query.QueryRowReference; import org.labkey.api.security.User; +import org.labkey.api.util.FileUtil; import org.labkey.api.view.ActionURL; import org.labkey.flow.FlowSettings; import org.labkey.flow.analysis.model.CompensationMatrix; @@ -38,9 +39,7 @@ import org.labkey.flow.query.FlowTableType; import jakarta.servlet.http.HttpServletRequest; -import java.io.File; import java.io.Serializable; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -89,7 +88,7 @@ static public FlowCompensationMatrix create(User user, Container container, Stri { data = svc.createData(container, FlowDataType.CompensationMatrix, name); } - data.setDataFileURI(new File(FlowSettings.getWorkingDirectory(), "compensation." + FlowDataHandler.EXT_DATA).toURI()); + data.setDataFileURI(FileUtil.appendName(FlowSettings.getWorkingDirectory(), "compensation." + FlowDataHandler.EXT_DATA).toURI()); data.save(user); AttributeSetHelper.doSave(attrs, user, data, log); flowComp = (FlowCompensationMatrix) FlowDataObject.fromData(data); @@ -105,8 +104,8 @@ public CompensationMatrix getCompensationMatrix() static public CompensationMatrix getCompensationMatrix(String name, AttributeSet attrs) { - TreeSet channelNames = new TreeSet(); - Map values = new HashMap(); + TreeSet channelNames = new TreeSet<>(); + Map values = new HashMap<>(); for (Map.Entry entry : attrs.getStatistics().entrySet()) { StatisticSpec spec = entry.getKey(); @@ -119,20 +118,20 @@ static public CompensationMatrix getCompensationMatrix(String name, AttributeSet channelNames.add(strChannel); values.put(spec.getParameter(), entry.getValue()); } - if (channelNames.size() == 0) + if (channelNames.isEmpty()) return null; CompensationMatrix ret = new CompensationMatrix(name); - String[] arrChannelNames = channelNames.toArray(new String[channelNames.size()]); + String[] arrChannelNames = channelNames.toArray(new String[0]); - for (int iChannel = 0; iChannel < arrChannelNames.length; iChannel ++) + for (String arrChannelName : arrChannelNames) { - Map channelValues = new TreeMap(); - for (int iChannelValue = 0; iChannelValue < arrChannelNames.length; iChannelValue ++) + Map channelValues = new TreeMap<>(); + for (String channelName : arrChannelNames) { - String key = arrChannelNames[iChannel] + ":" + arrChannelNames[iChannelValue]; - channelValues.put(arrChannelNames[iChannelValue], values.get(key)); + String key = arrChannelName + ":" + channelName; + channelValues.put(channelName, values.get(key)); } - ret.setChannel(arrChannelNames[iChannel], channelValues); + ret.setChannel(arrChannelName, channelValues); } return ret; } @@ -195,15 +194,17 @@ static public List getCompensationMatrices(Container con { return (List) FlowDataObject.fromDataType(container, FlowDataType.CompensationMatrix); } - static public List getUploadedCompensationMatrices(Container container) - { - List all = getCompensationMatrices(container); - List ret = new ArrayList(); - for (FlowCompensationMatrix comp : all) - { - if (comp.getRun() == null) - ret.add(comp); - } - return ret; - } + + //TODO remove? +// static public List getUploadedCompensationMatrices(Container container) +// { +// List all = getCompensationMatrices(container); +// List ret = new ArrayList<>(); +// for (FlowCompensationMatrix comp : all) +// { +// if (comp.getRun() == null) +// ret.add(comp); +// } +// return ret; +// } }