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