diff --git a/CHANGELOG.md b/CHANGELOG.md index c159244d..9bee128a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## version 6.3.0-SNAPSHOT *Released*: TBD * Update Commons Logging, Gradle, Gradle Plugins, HttpClient, HttpCore, and JSONObject versions +* Remove defunct FileNotification API and uses ## version 6.2.0 *Released*: 29 July 2024 diff --git a/build.gradle b/build.gradle index f08d83cd..ba38e4fc 100644 --- a/build.gradle +++ b/build.gradle @@ -77,7 +77,6 @@ dependencies { api "org.json:json:${jsonObjectVersion}" api "org.apache.httpcomponents.client5:httpclient5:${httpclient5Version}" api "org.apache.httpcomponents.core5:httpcore5:${httpcore5Version}" - implementation "net.sf.opencsv:opencsv:${opencsvVersion}" implementation "commons-logging:commons-logging:${commonsLoggingVersion}" implementation "commons-codec:commons-codec:${commonsCodecVersion}" } diff --git a/gradle.properties b/gradle.properties index 640c3342..ee172f4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,16 +12,13 @@ gradlePluginsVersion=6.1.0 commonsCodecVersion=1.17.1 commonsLoggingVersion=1.3.4 -httpclient5Version=5.4.1 -httpcore5Version=5.3.2 +httpclient5Version=5.4.2 +httpcore5Version=5.3.3 jsonObjectVersion=20250107 junitVersion=4.13.2 -# Obsolete? Switch to com.opencsv:opencsv 5.9? Or maybe just get rid of MS2SearchClient (only user)? -opencsvVersion=2.3 - #If iterating on the java client api and deploying it to a non-LabKey directory, uncomment and set this property (or set at command line), # and run the 'deployFatJar' task to create the jar with all dependencies and deploy it to the specified target. e.g., c:/somewhere/lib #javaClientDir= diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a793..e18bc253 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/org/labkey/remoteapi/ms2/StartSearchCommand.java b/src/org/labkey/remoteapi/ms2/StartSearchCommand.java deleted file mode 100644 index a4ea535f..00000000 --- a/src/org/labkey/remoteapi/ms2/StartSearchCommand.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2011-2014 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.remoteapi.ms2; - -import org.json.JSONObject; -import org.labkey.remoteapi.PostCommand; - -import java.util.List; -import java.util.Map; - -/** - * Initiates an MS2 search. - */ -public class StartSearchCommand extends PostCommand -{ - private String _protocol; - private String _path; - private List _files; - private final SearchEngine _searchEngine; - - /** The set of supported search engines, which may or may not be available on any given server */ - public enum SearchEngine { XTandem, Sequest, Mascot } - - /** - * @param searchEngine the search engine to be used for the analysis - * @param protocol the name of the search protocol that has already been defined on the server that should be used - * @param path the path relative to the pipeline root for the target container, in which the files will be present - * @param files the list of file names in the path specified that should be part of the search - */ - public StartSearchCommand(SearchEngine searchEngine, String protocol, String path, List files) - { - super("ms2-pipeline", "search" + searchEngine.name()); - _searchEngine = searchEngine; - setProtocol(protocol); - setPath(path); - setFiles(files); - } - - /** @return the name of the search protocol that has already been defined on the server that should be used */ - public String getProtocol() - { - return _protocol; - } - - /** @param protocol the name of the search protocol that has already been defined on the server that should be used */ - public void setProtocol(String protocol) - { - _protocol = protocol; - } - - /** @return the path relative to the pipeline root for the target container, in which the files will be present */ - public String getPath() - { - return _path; - } - - /** @param path the path relative to the pipeline root for the target container, in which the files will be present */ - public void setPath(String path) - { - _path = path; - } - - /** @return the list of file names in the path specified that should be part of the search */ - public List getFiles() - { - return _files; - } - - /** @param files the list of file names in the path specified that should be part of the search */ - public void setFiles(List files) - { - _files = files; - } - - @Override - protected Map createParameterMap() - { - Map result = super.createParameterMap(); - result.put("path", _path); - result.put("file", _files); - result.put("protocol", _protocol); - result.put("runSearch", true); - - return result; - } - - @Override - protected StartSearchResponse createResponse(String text, int status, String contentType, JSONObject json) - { - if (text.startsWith("ERROR=")) - { - throw new IllegalArgumentException(text.substring("ERROR=".length())); - } - return new StartSearchResponse(text, status, contentType, json); - } -} diff --git a/src/org/labkey/remoteapi/ms2/StartSearchResponse.java b/src/org/labkey/remoteapi/ms2/StartSearchResponse.java deleted file mode 100644 index 5d382815..00000000 --- a/src/org/labkey/remoteapi/ms2/StartSearchResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2011 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.remoteapi.ms2; - -import org.json.JSONObject; -import org.labkey.remoteapi.CommandResponse; - -public class StartSearchResponse extends CommandResponse -{ - public StartSearchResponse(String text, int statusCode, String contentType, JSONObject json) - { - super(text, statusCode, contentType, json); - } -} diff --git a/src/org/labkey/remoteapi/pipeline/FileNotificationCommand.java b/src/org/labkey/remoteapi/pipeline/FileNotificationCommand.java deleted file mode 100644 index 3df22152..00000000 --- a/src/org/labkey/remoteapi/pipeline/FileNotificationCommand.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2011 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.remoteapi.pipeline; - -import org.json.JSONObject; -import org.labkey.remoteapi.PostCommand; - -/** - * Notifies the server that files may have become available for the pipeline to process. Causes the server to - * look through all the jobs that are blocked, waiting for files, and release the ones whose files are now - * available. - */ -public class FileNotificationCommand extends PostCommand -{ - public FileNotificationCommand() - { - super("pipeline-analysis", "fileNotification"); - } - - @Override - protected FileNotificationResponse createResponse(String text, int status, String contentType, JSONObject json) - { - return new FileNotificationResponse(text, status, contentType, json); - } -} diff --git a/src/org/labkey/remoteapi/pipeline/FileNotificationResponse.java b/src/org/labkey/remoteapi/pipeline/FileNotificationResponse.java deleted file mode 100644 index 8f2e545b..00000000 --- a/src/org/labkey/remoteapi/pipeline/FileNotificationResponse.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2011 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.remoteapi.pipeline; - -import org.json.JSONObject; -import org.labkey.remoteapi.CommandResponse; - -/** - * Server response from FileNotificationCommand. Contains no return values. - */ -public class FileNotificationResponse extends CommandResponse -{ - public FileNotificationResponse(String text, int statusCode, String contentType, JSONObject json) - { - super(text, statusCode, contentType, json); - } -} diff --git a/src/org/labkey/remoteapi/test/MS2SearchClient.java b/src/org/labkey/remoteapi/test/MS2SearchClient.java deleted file mode 100644 index f1c20749..00000000 --- a/src/org/labkey/remoteapi/test/MS2SearchClient.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2011-2015 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.remoteapi.test; - -import au.com.bytecode.opencsv.CSVReader; -import org.labkey.remoteapi.CommandException; -import org.labkey.remoteapi.Connection; -import org.labkey.remoteapi.assay.Batch; -import org.labkey.remoteapi.assay.Data; -import org.labkey.remoteapi.assay.Run; -import org.labkey.remoteapi.assay.SaveAssayBatchCommand; -import org.labkey.remoteapi.ms2.StartSearchCommand; - -import java.io.*; -import java.util.*; - -/** - * Demo code that accepts one or more CSV files on the command line. It creates assay runs to hold the metadata - * from the CSV, and then initiates MS2 searches on the files. If the files are not yet available, the jobs will block - * until the server is notified that files are available (see PipelineFileAvailableClient). - * - * Expects to receive the path to one or more CSV files on the command line. Each CSV is required to have the following - * columns: - * - * FileName: the name of the mzXML or RAW file to be searched - * Path: the path to the file - * Sample: the name of the sample. Used to determine if files are fractions or independent samples. - * LabKeyFolder: the target folder in LabKey Server - * ProtocolToRun: the name of the existing search protocol to be used when searching the files - * - * If other columns are present in the CSV, they will be associated with the assay runs as run properties if the assay - * design includes run properties with the same names. - * - * By default looks for a config.properties in the working directory, but the location can be specified with a - * -config=<PATH TO CONFIG FILE> argument. - * - * Expects the following config properties: - * baseServerURL: base URL of the LabKey Server, such as "http://www.labkey.org" - * username: credentials for logging in - * password: credentials for logging in - * pipelineRoot: the path to the pipeline root for the target folder. Used to pass a relative path to the server. - * assayId: the rowId of the GPAT assay design to be used for storing metadata - * searchEngine: the name of the MS2 search engine to use. Supported values are XTandem, Sequest, and Mascot. - * debug: (Optional) If true, print verbose HTTP connection debugging information - */ -public class MS2SearchClient -{ - /** Simple bean class to hold the values that uniquely identify the files to be submitted in one search */ - private static class SearchInfo - { - private final String _sample; - private final String _protocol; - private final String _folder; - private final String _path; - - private SearchInfo(String sample, String protocol, String folder, String path) - { - _sample = sample; - _protocol = protocol; - _folder = folder; - _path = path; - } - - public String getProtocol() - { - return _protocol; - } - - public String getFolder() - { - return _folder; - } - - public String getPath() - { - return _path; - } - - public boolean equals(Object o) - { - if (this == o) - return true; - if (!(o instanceof SearchInfo)) - return false; - SearchInfo that = (SearchInfo) o; - if (_folder == null ? that._folder != null : !_folder.equals(that._folder)) - return false; - if (_path == null ? that._path != null : !_path.equals(that._path)) - return false; - if (_protocol == null ? that._protocol != null : !_protocol.equals(that._protocol)) - return false; - return _sample == null ? that._sample == null : _sample.equals(that._sample); - } - - public int hashCode() - { - int result = _sample == null ? 0 : _sample.hashCode(); - result = 31 * result + (_protocol == null ? 0 : _protocol.hashCode()); - result = 31 * result + (_folder == null ? 0 : _folder.hashCode()); - result = 31 * result + (_path == null ? 0 : _path.hashCode()); - return result; - } - - } - - public static void main(String... args) throws Exception - { - ClientConfig config = new ClientConfig(args); - - int assayId = getAssayId(config); - - // Map from target folder path to assay batch - Map batches = new HashMap<>(); - - // Map from MS2 search info to the list of file names to be searched - Map> searches = new HashMap<>(); - - parseCSVs(args, batches, searches); - - Connection connection = config.createConnection(); - try - { - submitAssayBatches(assayId, batches, connection); - submitSearches(config, searches, connection); - } - catch (CommandException e) - { - System.err.println((new StringBuilder()).append("Failure! Response code: ").append(e.getStatusCode()).toString()); - e.printStackTrace(); - System.err.println(); - if (e.getResponseText() != null) - { - System.err.println("Response text: "); - System.err.println(e.getResponseText()); - } - System.exit(1); - } - } - - /** - * Initiates MS2 searches - */ - private static void submitSearches(ClientConfig config, Map> searches, Connection connection) - throws IOException, CommandException - { - String pipelineRoot = config.getProperty("pipelineRoot"); - String searchEngineName = config.getProperty("searchEngine"); - - StartSearchCommand.SearchEngine searchEngine = null; - - for (StartSearchCommand.SearchEngine engine : StartSearchCommand.SearchEngine.values()) - { - if (engine.name().equalsIgnoreCase(searchEngineName)) - { - searchEngine = engine; - } - } - - if (searchEngine == null) - { - throw new IllegalArgumentException("searchEngine '" + searchEngineName + "' is not one of the available options: " + Arrays.asList(StartSearchCommand.SearchEngine.values())); - } - - for (Map.Entry> entry : searches.entrySet()) - { - SearchInfo searchInfo = entry.getKey(); - - // Figure out a relative path from the pipeline root - String fullPath = searchInfo.getPath(); - if (!fullPath.toLowerCase().startsWith(pipelineRoot.toLowerCase())) - { - throw new IllegalArgumentException((new StringBuilder()).append("Could not determine relative path for '").append(fullPath).toString()); - } - String relativePath = fullPath.substring(pipelineRoot.length()); - relativePath = relativePath.replace('\\', '/'); - if (!relativePath.startsWith("/")) - { - relativePath = "/" + relativePath; - } - List fileNames = entry.getValue(); - - System.out.print("Submitting search using protocol " + searchInfo.getProtocol() + " to " + searchInfo.getFolder() + ", with " + fileNames.size() + " files"); - StartSearchCommand startCommand = new StartSearchCommand(searchEngine, searchInfo.getProtocol(), relativePath, fileNames); - startCommand.execute(connection, searchInfo.getFolder()); - } - } - - /** - * Iterate over all of the batch objects and submit them to the right target folder - * - * @param assayId rowId of the target assay design - * @param batches a map from target folder to assay batch - */ - private static void submitAssayBatches(int assayId, Map batches, Connection connection) - throws IOException, CommandException - { - for (Map.Entry entry : batches.entrySet()) - { - Batch batch = entry.getValue(); - String targetFolder = entry.getKey(); - SaveAssayBatchCommand command = new SaveAssayBatchCommand(assayId, batch); - System.out.print("Submitting metadata from " + batch + " to " + targetFolder + ", describing " + batch.getRuns().size() + " files"); - command.execute(connection, targetFolder); - } - } - - /** - * Parse all of the CSVs passed on the command line and build up the list of assay batches to be inserted, - * and the searches to be initiated. - */ - private static void parseCSVs(String[] args, Map batches, Map> searches) - throws IOException - { - for (String arg : args) - { - // Skip -config= or other non-CSV arguments - if (!arg.startsWith("-")) - { - File csvFile = new File(arg); - System.out.println("Processing " + csvFile); - List lines; - InputStream in = new FileInputStream(csvFile); - try - { - // Parse the CSVs into lists of string values - Reader reader = new InputStreamReader(in); - CSVReader csvReader = new CSVReader(reader, ',', '"', '~'); - lines = csvReader.readAll(); - } - finally - { - in.close(); - } - - if (lines.size() < 2) - { - throw new IllegalArgumentException("Expected to have at least two rows in CSV, one with headers and others with data in " + csvFile.getPath()); - } - - String headers[] = lines.get(0); - // Look at each data row within the CSV - for (int i = 1; i < lines.size(); i++) - { - String[] line = lines.get(i); - - // Skip lines that are completely empty - boolean blankLink = true; - for (String value : line) - { - if (value != null && !value.trim().isEmpty()) - { - blankLink = false; - break; - } - } - if (blankLink) - { - continue; - } - - // Pull out the required values - String fileName = getValue(line, headers, "FileName", i); - String path = getValue(line, headers, "Path", i); - String sample = getValue(line, headers, "Sample", i); - String folder = getValue(line, headers, "LabKeyFolder", i); - String protocol = getValue(line, headers, "ProtocolToRun", i); - - // Create a map of all the properties. If the assay design has run properties with names that - // match, the values will be stored with the run. - Map runProperties = new HashMap<>(); - for (int columnIndex = 0; columnIndex < line.length; columnIndex++) - { - runProperties.put(headers[columnIndex], line[columnIndex]); - } - - // We want to create one batch per folder, so grab an existing batch if we have one - Batch batch = batches.get(folder); - if (batch == null) - { - // This is the first run for this folder, so create a new batch - batch = new Batch(); - batch.setName(csvFile.getName()); - batches.put(folder, batch); - } - - addRunToBatch(batch, fileName, path, runProperties); - - SearchInfo info = new SearchInfo(sample, protocol, folder, path); - List files = searches.get(info); - if (files == null) - { - files = new ArrayList(); - searches.put(info, files); - } - files.add(fileName); - } - } - } - } - - /** @return the parsed assayId config property as an int */ - private static int getAssayId(ClientConfig config) - { - String assayIdString = config.getProperty("assayId"); - int assayId; - try - { - assayId = Integer.parseInt(assayIdString); - } - catch (NumberFormatException e) - { - throw new IllegalArgumentException((new StringBuilder()).append("Could not parse assayId: ").append(assayIdString).toString(), e); - } - return assayId; - } - - /** - * @return the value for the given column in the specified line. - * @param lineNumber used only to build up an error message if the value can't be found - */ - private static String getValue(String line[], String headers[], String columnName, int lineNumber) - { - int columnIndex = findIndex(headers, columnName); - if (columnIndex >= line.length) - throw new IllegalArgumentException((new StringBuilder()).append("Row ").append(lineNumber).append(" is incomplete in CSV file. It contains fewer columns than the header does.").toString()); - String result = line[columnIndex]; - if (result == null || result.trim().equals("")) - throw new IllegalArgumentException((new StringBuilder()).append("Row ").append(lineNumber).append(" is incomplete in CSV file, it does not include a value for '").append(columnName).append("'").toString()); - else - return result.trim(); - } - - /** Adds a new run to the assay batch to store the metadata for the current input MS2 file */ - private static void addRunToBatch(Batch batch, String fileName, String path, Map runProperties) - { - Run run = new Run(); - run.setName(fileName); - run.getProperties().putAll(runProperties); - batch.getRuns().add(run); - List outputFiles = new ArrayList<>(); - Data data = new Data(); - data.setAbsolutePath(path + File.separator + fileName); - outputFiles.add(data); - run.setDataOutputs(outputFiles); - } - - /** Finds a column by name given the column headers */ - private static int findIndex(String[] headers, String propertyName) - { - for (int i = 0; i < headers.length; i++) - { - if (propertyName.equalsIgnoreCase(headers[i])) - return i; - } - - throw new IllegalArgumentException("Unable to find required property '" + propertyName + "' in input CSV file"); - } -} diff --git a/src/org/labkey/remoteapi/test/PipelineFileAvailableClient.java b/src/org/labkey/remoteapi/test/PipelineFileAvailableClient.java deleted file mode 100644 index ccfece58..00000000 --- a/src/org/labkey/remoteapi/test/PipelineFileAvailableClient.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2011-2015 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.remoteapi.test; - -import org.labkey.remoteapi.CommandException; -import org.labkey.remoteapi.Connection; -import org.labkey.remoteapi.pipeline.FileNotificationCommand; - -/** - * Demo code that notifies server that files may become available under a pipeline root, which releases - * queued pipeline jobs that are blocked awaiting those files. - * - * By default looks for a config.properties in the working directory, but the location can be specified with a - * -config=<PATH TO CONFIG FILE> argument. - * - * Expects the following config properties: - * baseServerURL: base URL of the LabKey Server, such as "http://www.labkey.org" - * username: credentials for logging in - * password: credentials for logging in - * folder: Path of the LabKey Server container to which the notification should be directed - * debug: (Optional) If true, print verbose HTTP connection debugging information - * - */ -public class PipelineFileAvailableClient -{ - - public static void main(String... args) throws Exception - { - ClientConfig config = new ClientConfig(args); - Connection connection = config.createConnection(); - - try - { - // Create the command an execute it against our target folder - FileNotificationCommand notificationCommand = new FileNotificationCommand(); - notificationCommand.execute(connection, config.getProperty("folder")); - System.out.println("Success!"); - } - catch(CommandException e) - { - System.err.println((new StringBuilder()).append("Failure! Response code: ").append(e.getStatusCode()).toString()); - e.printStackTrace(); - System.err.println(); - if(e.getResponseText() != null) - { - System.err.println("Response text: "); - System.err.println(e.getResponseText()); - } - } - } -}