diff --git a/datastore_server/source/core-plugins/file-system-plugin-example/1/dss/file-system-plugins/data-set-types-with-data-sets-and-files-from-parents/plugin.properties b/datastore_server/source/core-plugins/file-system-plugin-example/1/dss/file-system-plugins/data-set-types-with-data-sets-and-files-from-parents/plugin.properties new file mode 100644 index 0000000000000000000000000000000000000000..677ff5ae26712a96c717be24c70882eb1c6e7822 --- /dev/null +++ b/datastore_server/source/core-plugins/file-system-plugin-example/1/dss/file-system-plugins/data-set-types-with-data-sets-and-files-from-parents/plugin.properties @@ -0,0 +1,2 @@ +resolver-class = ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.plugins.V3DataSetTypeResolver +code = __data_set_types__ diff --git a/datastore_server/source/core-plugins/file-system-plugin-example/1/dss/file-system-plugins/sample-types-with-data-sets/plugin.properties b/datastore_server/source/core-plugins/file-system-plugin-example/1/dss/file-system-plugins/sample-types-with-data-sets/plugin.properties new file mode 100644 index 0000000000000000000000000000000000000000..b1424b084cb952ce74eda386ace9da34f9bf050c --- /dev/null +++ b/datastore_server/source/core-plugins/file-system-plugin-example/1/dss/file-system-plugins/sample-types-with-data-sets/plugin.properties @@ -0,0 +1,2 @@ +resolver-class = ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.plugins.V3SampleTypeResolver +code = __sample_types__ diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3DataSetContentResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3DataSetContentResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..212ea49ce4badbc39568858e1ce75cb0a3137066 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3DataSetContentResolver.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016 ETH Zuerich, CISD + * + * 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 ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3; + +import java.util.Collections; +import java.util.Map; + +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.IDataSetId; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFile; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpNonExistingFile; + +/** + * Resolves the content of the data set. Assumes that the first part of the path is data set code + * + * @author Jakub Straszewski + */ +public class V3DataSetContentResolver implements V3Resolver +{ + String dataSetCode; + + public V3DataSetContentResolver(String dataSetCode) + { + this.dataSetCode = dataSetCode; + } + + @Override + public V3FtpFile resolve(String fullPath, String[] subPath, FtpPathResolverContext context) + { + // this fetching of data set is for authorization purposes, as content provider doesn't check if user has access to data set + IDataSetId id = new DataSetPermId(dataSetCode); + Map<IDataSetId, DataSet> dataSets = + context.getV3Api().getDataSets(context.getSessionToken(), Collections.singletonList(id), new DataSetFetchOptions()); + + if (dataSets.get(id) == null) + { + return new V3FtpNonExistingFile(fullPath, "Path doesn't exist or unauthorized"); + } + + IHierarchicalContent content = context.getContentProvider().asContent(dataSetCode); + V3HierarchicalContentResolver resolver = new V3HierarchicalContentResolver(content); + return resolver.resolve(fullPath, subPath, context); + } +} \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ExperimentLevelResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ExperimentLevelResolver.java index c69223d7085705f3a943093021a7ec87e3e4079d..6af0152c88148ded6e872e8b10a96f5b0fb3f14a 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ExperimentLevelResolver.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ExperimentLevelResolver.java @@ -24,7 +24,6 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet; import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment; import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.fetchoptions.ExperimentFetchOptions; import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.IExperimentId; -import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpDirectoryResponse; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFile; @@ -59,11 +58,8 @@ class V3ExperimentLevelResolver implements V3Resolver } else { String dataSetCode = subPath[0]; - IHierarchicalContent content = context.getContentProvider().asContent(dataSetCode); String[] remaining = Arrays.copyOfRange(subPath, 1, subPath.length); - V3HierarchicalContentResolver resolver = new V3HierarchicalContentResolver(content); - return resolver.resolve(fullPath, remaining, context); + return new V3DataSetContentResolver(dataSetCode).resolve(fullPath, remaining, context); } } - } \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3Resolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3Resolver.java index 9f1a126b312b7a50c6d49ef3d1e2e8bc8e81ec93..ec1f7fcadbc3847f3f1a6cbdf27ce22a74c8125a 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3Resolver.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3Resolver.java @@ -24,5 +24,5 @@ public interface V3Resolver /** * Create a ftp file which has specified full path, resolving the local path specified as an array of path items. */ - public abstract V3FtpFile resolve(String fullPath, String[] pathItems, FtpPathResolverContext resolverContext); -} + V3FtpFile resolve(String fullPath, String[] pathItems, FtpPathResolverContext resolverContext); +} \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3PluginResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/plugins/V3DataSetTypeResolver.java similarity index 92% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3PluginResolver.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/plugins/V3DataSetTypeResolver.java index 2b20c09cde0c9fd85b5bee0415c61008321bf863..8fe8d3acce526cb6a503884189c3f3eaae4acc06 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3PluginResolver.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/plugins/V3DataSetTypeResolver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3; +package ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.plugins; import java.util.ArrayList; import java.util.Collections; @@ -31,15 +31,24 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetTypeSearch import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContentNode; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.V3Resolver; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpDirectoryResponse; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFile; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFileResponse; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpNonExistingFile; import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider; -class V3PluginResolver implements V3Resolver +/** + * Resolves paths of a form /DATA_SET_TYPE/DATA_SET_CODE/{files} <br> + * / - list all data set types <br> + * /UNKNOWN - list all data sets of type UNKNOWN <br> + * /UNKNOWN/20193763213-123 - list in one directory all files belonging to the data set 20193763213-123 or any of it's parents <br> + * /UNKNOWN/20193763213-123/test0123.png - download the content of a listed file + * + * @author Jakub Straszewski + */ +public class V3DataSetTypeResolver implements V3Resolver { - @Override public V3FtpFile resolve(String fullPath, String[] subPath, FtpPathResolverContext context) { diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/plugins/V3SampleTypeResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/plugins/V3SampleTypeResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..e612586413486d6c5d0909884bc45ac8d2a75d11 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/plugins/V3SampleTypeResolver.java @@ -0,0 +1,128 @@ +/* + * Copyright 2016 ETH Zuerich, CISD + * + * 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 ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.plugins; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.SampleType; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleTypeFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleTypeSearchCriteria; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.V3DataSetContentResolver; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.V3Resolver; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpDirectoryResponse; +import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.file.V3FtpFile; + +/** + * Resolves paths of type "/SAMPLE_TYPE/SAMPLE_CODE/DATASET_CODE/data set content <br> + * / - list all listable sample types<br> + * /PLATE - list all sample codes of samples of type plate<br> + * /PLATE/TEST-1 - list all datasets belonging to some sample of type PLATE and code TEST-1<br> + * /PLATE/TEST-1/20183213123-43 - list file contents of data set 20183213123-43 <br> + * /PLATE/TEST-1/20183213123-43/original - list contents of a directory inside a data set<br> + * /PLATE/TEST-1/20183213123-43/original/file.txt - download content of file.txt<br> + * + * @author Jakub Straszewski + */ +public class V3SampleTypeResolver implements V3Resolver +{ + @Override + public V3FtpFile resolve(String fullPath, String[] subPath, FtpPathResolverContext context) + { + if (subPath.length == 0) + { + return listSampleTypes(fullPath, context); + } + + String sampleType = subPath[0]; + if (subPath.length == 1) + { + return listSamplesOfGivenType(fullPath, sampleType, context); + } + + String sampleCode = subPath[1]; + if (subPath.length == 2) + { + return listDataSetsForGivenSampleTypeAndCode(fullPath, sampleType, sampleCode, context); + } + + String dataSetCode = subPath[2]; + String[] remaining = Arrays.copyOfRange(subPath, 3, subPath.length); + return new V3DataSetContentResolver(dataSetCode).resolve(fullPath, remaining, context); + } + + private V3FtpFile listDataSetsForGivenSampleTypeAndCode(String fullPath, String sampleTypeCode, String sampleCode, FtpPathResolverContext context) + { + DataSetSearchCriteria searchCriteria = new DataSetSearchCriteria(); + searchCriteria.withSample().withType().withCode().thatEquals(sampleTypeCode); + searchCriteria.withSample().withCode().thatEquals(sampleCode); + List<DataSet> dataSets = context.getV3Api().searchDataSets(context.getSessionToken(), searchCriteria, new DataSetFetchOptions()).getObjects(); + + V3FtpDirectoryResponse result = new V3FtpDirectoryResponse(fullPath); + for (DataSet dataSet : dataSets) + { + result.addDirectory(dataSet.getCode()); + } + return result; + } + + private V3FtpFile listSamplesOfGivenType(String fullPath, String sampleType, FtpPathResolverContext context) + { + SampleSearchCriteria searchCriteria = new SampleSearchCriteria(); + searchCriteria.withType().withCode().thatEquals(sampleType); + List<Sample> samples = context.getV3Api().searchSamples(context.getSessionToken(), searchCriteria, new SampleFetchOptions()).getObjects(); + + // as codes can overlap, we want to create only one entry per code + HashSet<String> sampleCodes = new HashSet<>(); + + V3FtpDirectoryResponse result = new V3FtpDirectoryResponse(fullPath); + for (Sample sample : samples) + { + if (false == sampleCodes.contains(sample.getCode())) + { + result.addDirectory(sample.getCode()); + sampleCodes.add(sample.getCode()); + } + } + return result; + } + + private V3FtpFile listSampleTypes(String fullPath, FtpPathResolverContext context) + { + SampleTypeSearchCriteria searchCriteria = new SampleTypeSearchCriteria(); + searchCriteria.withListable().thatEquals(true); + List<SampleType> sampleTypes = + context.getV3Api().searchSampleTypes(context.getSessionToken(), searchCriteria, new SampleTypeFetchOptions()) + .getObjects(); + + V3FtpDirectoryResponse response = new V3FtpDirectoryResponse(fullPath); + for (SampleType type : sampleTypes) + { + response.addDirectory(type.getCode()); + } + return response; + } + +} \ No newline at end of file