diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java
index c76784fdd0bd921dd417b390467823adfd1acaf4..bd007981b481a2aa6568af417e8c96e8f1e16dd4 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/cifs/DataSetCifsView.java
@@ -40,6 +40,7 @@ import org.apache.ftpserver.ftplet.FtpFile;
 import org.apache.log4j.Logger;
 import org.springframework.extensions.config.ConfigElement;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
@@ -48,38 +49,44 @@ import ch.systemsx.cisd.openbis.dss.generic.server.ftp.Cache;
 import ch.systemsx.cisd.openbis.dss.generic.server.ftp.DSSFileSystemView;
 import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverConfig;
 import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverRegistry;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.IFtpPathResolverRegistry;
 import ch.systemsx.cisd.openbis.dss.generic.server.ftp.NonExistingFtpFile;
 import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
 import ch.systemsx.cisd.openbis.generic.shared.IServiceForDataStoreServer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class DataSetCifsView implements DiskInterface
 {
     private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, DataSetCifsView.class);
-    
+
     private Cache cache;
+
     private IServiceForDataStoreServer dssService;
+
     private IGeneralInformationService generalInfoService;
-    
-    private FtpPathResolverRegistry pathResolverRegistry;
+
+    private IApplicationServerApi v3api;
+
+    private IFtpPathResolverRegistry pathResolverRegistry;
+
     public DataSetCifsView()
     {
         operationLog.info("CIFS view onto the data store created");
         cache = new Cache(SystemTimeProvider.SYSTEM_TIME_PROVIDER);
     }
 
-    DataSetCifsView(IServiceForDataStoreServer openBisService, IGeneralInformationService generalInfoService, Cache cache)
+    DataSetCifsView(IServiceForDataStoreServer openBisService, IGeneralInformationService generalInfoService, IApplicationServerApi v3api,
+            Cache cache)
     {
         this.dssService = openBisService;
         this.generalInfoService = generalInfoService;
+        this.v3api = v3api;
         this.cache = cache;
     }
-    
+
     @Override
     public DeviceContext createContext(String shareName, ConfigElement args) throws DeviceContextException
     {
@@ -95,7 +102,7 @@ public class DataSetCifsView implements DiskInterface
     {
         operationLog.info("tree " + tree + " opened");
     }
-    
+
     @Override
     public void treeClosed(SrvSession sess, TreeConnection tree)
     {
@@ -186,7 +193,7 @@ public class DataSetCifsView implements DiskInterface
             }
             operationLog.info("Open file '" + path + "'.");
             NetworkFile networkFile = new CifsFile(file);
-            
+
             networkFile.setAttributes(FileAttribute.ReadOnly);
             networkFile.setCreationDate(file.getLastModified());
             networkFile.setModifyDate(file.getLastModified());
@@ -208,7 +215,7 @@ public class DataSetCifsView implements DiskInterface
     }
 
     @Override
-    public int readFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufPos, 
+    public int readFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufPos,
             int size, long filePos) throws IOException
     {
         if (file.isDirectory())
@@ -296,7 +303,8 @@ public class DataSetCifsView implements DiskInterface
         try
         {
             String sessionToken = getSessionToken(session);
-            return new DSSFileSystemView(sessionToken, getDssService(), getGeneralInfoService(), pathResolverRegistry, cache);
+            return new DSSFileSystemView(sessionToken, getDssService(), getGeneralInfoService(), getApplicationServerApi(), pathResolverRegistry,
+                    cache);
         } catch (FtpException ex)
         {
             throw CheckedExceptionTunnel.wrapIfNecessary(ex);
@@ -316,7 +324,7 @@ public class DataSetCifsView implements DiskInterface
         }
         return dssService;
     }
-    
+
     private IGeneralInformationService getGeneralInfoService()
     {
         if (generalInfoService == null)
@@ -325,7 +333,16 @@ public class DataSetCifsView implements DiskInterface
         }
         return generalInfoService;
     }
-    
+
+    private IApplicationServerApi getApplicationServerApi()
+    {
+        if (v3api == null)
+        {
+            v3api = ServiceProvider.getV3ApplicationService();
+        }
+        return v3api;
+    }
+
     private String getSessionToken(SrvSession sess)
     {
         ClientInfo client = sess.getClientInformation();
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemView.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemView.java
index 48ffa03f1dbe6fb9c68fac19e07c5cfe211f324c..5cf17b1f02a4065c188f3e197589358d0f0cfd91 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemView.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemView.java
@@ -33,6 +33,7 @@ import org.apache.ftpserver.ftplet.FtpException;
 import org.apache.ftpserver.ftplet.FtpFile;
 import org.apache.log4j.Logger;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.logging.LogCategory;
@@ -101,26 +102,30 @@ public class DSSFileSystemView implements FileSystemView
 
     private final IGeneralInformationService generalInfoService;
 
+    private final IApplicationServerApi v3api;
+
     private FtpFile workingDirectory;
 
     private final IFtpPathResolverRegistry pathResolverRegistry;
 
     public DSSFileSystemView(String sessionToken, final IServiceForDataStoreServer service,
-            IGeneralInformationService generalInfoService,
+            IGeneralInformationService generalInfoService, IApplicationServerApi v3api,
             IFtpPathResolverRegistry pathResolverRegistry) throws FtpException
     {
-        this(sessionToken, service, generalInfoService, pathResolverRegistry, 
+        this(sessionToken, service, generalInfoService, v3api, pathResolverRegistry,
                 new Cache(SystemTimeProvider.SYSTEM_TIME_PROVIDER));
     }
+
     public DSSFileSystemView(String sessionToken, final IServiceForDataStoreServer service,
-            IGeneralInformationService generalInfoService,
+            IGeneralInformationService generalInfoService, IApplicationServerApi v3api,
             IFtpPathResolverRegistry pathResolverRegistry, Cache cache) throws FtpException
     {
         this.sessionToken = sessionToken;
         this.service =
-                (IServiceForDataStoreServer) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]
-                { IServiceForDataStoreServer.class }, new ServiceInvocationHandler(service));
+                (IServiceForDataStoreServer) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { IServiceForDataStoreServer.class },
+                        new ServiceInvocationHandler(service));
         this.generalInfoService = generalInfoService;
+        this.v3api = v3api;
         this.pathResolverRegistry = pathResolverRegistry;
         this.workingDirectory = getFile(FtpConstants.ROOT_DIRECTORY, cache);
     }
@@ -161,7 +166,7 @@ public class DSSFileSystemView implements FileSystemView
         try
         {
             FtpPathResolverContext context =
-                    new FtpPathResolverContext(sessionToken, service, generalInfoService,
+                    new FtpPathResolverContext(sessionToken, service, generalInfoService, v3api,
                             pathResolverRegistry, cache);
             return pathResolverRegistry.resolve(normalizedPath, context);
         } catch (RuntimeException rex)
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpPathResolverContext.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpPathResolverContext.java
index 518e66315f5b77c7f560d945292d755b9ec19246..f24a7204e42bed9fefac4556361be67cbb73ac61 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpPathResolverContext.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpPathResolverContext.java
@@ -22,8 +22,11 @@ import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.server.ISessionTokenProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
 import ch.systemsx.cisd.openbis.generic.shared.IServiceForDataStoreServer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet;
@@ -48,18 +51,23 @@ public class FtpPathResolverContext implements ISessionTokenProvider
 
     private final IGeneralInformationService generalInfoService;
 
+    private final IApplicationServerApi v3api;
+
     private final IFtpPathResolverRegistry resolverRegistry;
 
     private final Cache cache;
 
+    private IHierarchicalContentProvider contentProvider;
+
     public FtpPathResolverContext(String sessionToken, IServiceForDataStoreServer service,
-            IGeneralInformationService generalInfoService,
+            IGeneralInformationService generalInfoService, IApplicationServerApi v3api,
             IFtpPathResolverRegistry resolverRegistry, Cache cache)
     {
         this.sessionToken = sessionToken;
         this.service = service;
         this.generalInfoService = generalInfoService;
         this.resolverRegistry = resolverRegistry;
+        this.v3api = v3api;
         this.cache = cache;
     }
 
@@ -74,11 +82,25 @@ public class FtpPathResolverContext implements ISessionTokenProvider
         return service;
     }
 
+    public IApplicationServerApi getV3Api()
+    {
+        return v3api;
+    }
+
     public Cache getCache()
     {
         return cache;
     }
 
+    public IHierarchicalContentProvider getContentProvider()
+    {
+        if (contentProvider == null)
+        {
+            contentProvider = ServiceProvider.getHierarchicalContentProvider();
+        }
+        return contentProvider.cloneFor(this);
+    }
+
     public DataSet getDataSet(String dataSetCode)
     {
         DataSet dataSet = cache.getDataSet(dataSetCode);
@@ -170,7 +192,7 @@ public class FtpPathResolverContext implements ISessionTokenProvider
         }
         return availableDataSets;
     }
-    
+
     public IGeneralInformationService getGeneralInfoService()
     {
         return generalInfoService;
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpServer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpServer.java
index bf8cd934175ae1a4ef6b142f6be52c4c61b34ac5..8fd9eb20ceb88ed64b29214d951ecffb1bfac9e5 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpServer.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/FtpServer.java
@@ -69,6 +69,7 @@ import org.apache.sshd.server.SshFile;
 import org.apache.sshd.server.session.ServerSession;
 import org.apache.sshd.server.sftp.SftpSubsystem;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.filesystem.FileUtilities;
@@ -76,6 +77,7 @@ import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.properties.PropertyParametersUtil;
 import ch.systemsx.cisd.common.utilities.SystemTimeProvider;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.v3.V3FtpPathResolverRegistry;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DssPropertyParametersUtil;
 import ch.systemsx.cisd.openbis.generic.shared.IServiceForDataStoreServer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
@@ -104,19 +106,23 @@ public class FtpServer implements FileSystemFactory, org.apache.sshd.server.File
 
     private final IGeneralInformationService generalInfoService;
 
+    private final IApplicationServerApi v3api;
+
     private SshServer sshServer;
 
-    public FtpServer(IServiceForDataStoreServer openBisService, IGeneralInformationService generalInfoService,
+    public FtpServer(IServiceForDataStoreServer openBisService, IGeneralInformationService generalInfoService, IApplicationServerApi v3api,
             UserManager userManager) throws Exception
     {
         this.openBisService = openBisService;
         this.generalInfoService = generalInfoService;
+        this.v3api = v3api;
         this.userManager = userManager;
         Properties ftpProperties = PropertyParametersUtil.extractSingleSectionProperties(
                 DssPropertyParametersUtil.loadServiceProperties(), "ftp.server", true).getProperties();
         this.config = new FtpServerConfig(ftpProperties);
         FtpPathResolverConfig resolverConfig = new FtpPathResolverConfig(ftpProperties);
-        this.pathResolverRegistry = new FtpPathResolverRegistry(resolverConfig);
+        this.pathResolverRegistry = new V3FtpPathResolverRegistry(resolverConfig);
+        // this.pathResolverRegistry = new FtpPathResolverRegistry(resolverConfig);
 
         if (config.isStartServer())
         {
@@ -266,7 +272,7 @@ public class FtpServer implements FileSystemFactory, org.apache.sshd.server.File
         if (user instanceof FtpUser)
         {
             String sessionToken = ((FtpUser) user).getSessionToken();
-            return new DSSFileSystemView(sessionToken, openBisService, generalInfoService,
+            return new DSSFileSystemView(sessionToken, openBisService, generalInfoService, v3api,
                     pathResolverRegistry);
         } else
         {
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
new file mode 100644
index 0000000000000000000000000000000000000000..005b2759cfe189dcbadaf2dd7695b104e056e704
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ExperimentLevelResolver.java
@@ -0,0 +1,71 @@
+/*
+ * 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.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ftpserver.ftplet.FtpFile;
+
+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;
+
+class V3ExperimentLevelResolver extends V3Resolver
+{
+    private IExperimentId experimentId;
+
+    public V3ExperimentLevelResolver(IExperimentId experimentId, FtpPathResolverContext resolverContext)
+    {
+        super(resolverContext);
+        this.experimentId = experimentId;
+    }
+
+    @Override
+    public FtpFile resolve(String fullPath, String[] subPath)
+    {
+        if (subPath.length == 0)
+        {
+            ExperimentFetchOptions fetchOptions = new ExperimentFetchOptions();
+            fetchOptions.withDataSets();
+
+            Map<IExperimentId, Experiment> experiments = api.getExperiments(sessionToken, Collections.singletonList(experimentId), fetchOptions);
+            Experiment exp = experiments.get(experimentId);
+
+            List<FtpFile> files = new LinkedList<>();
+            for (DataSet dataSet : exp.getDataSets())
+            {
+                files.add(createDirectoryScaffolding(fullPath, dataSet.getCode()));
+            }
+            return createDirectoryWithContent(fullPath, files);
+        } else
+        {
+            String dataSetCode = subPath[0];
+            IHierarchicalContent content = resolverContext.getContentProvider().asContent(dataSetCode);
+            String[] remaining = Arrays.copyOfRange(subPath, 1, subPath.length);
+            V3HierarchicalContentResolver resolver = new V3HierarchicalContentResolver(content, resolverContext);
+            return resolver.resolve(fullPath, remaining);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3FtpPathResolverRegistry.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3FtpPathResolverRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3fbeba6256a0cd6ef25c342b48c5b43a7830a61
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3FtpPathResolverRegistry.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2011 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 org.apache.ftpserver.ftplet.FtpFile;
+import org.apache.log4j.Logger;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverConfig;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.IFtpPathResolver;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.IFtpPathResolverRegistry;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
+
+/**
+ * A registry of ftp resolvers. It keeps the style of old-style resolver regisrty, but actually only calls itself root resolver.
+ * 
+ * @author Jakub Straszewski
+ */
+public class V3FtpPathResolverRegistry implements IFtpPathResolverRegistry
+{
+
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            V3FtpPathResolverRegistry.class);
+
+    private IApplicationServerApi v3api;
+
+    public IApplicationServerApi getV3api()
+    {
+        if (v3api == null)
+            v3api = ServiceProvider.getV3ApplicationService();
+        return v3api;
+    }
+
+    /**
+     * initializes the registry with all known {@link IFtpPathResolver}-s.
+     */
+    public V3FtpPathResolverRegistry(FtpPathResolverConfig config)
+    {
+
+    }
+
+    @Override
+    public FtpFile resolve(String path, FtpPathResolverContext resolverContext)
+    {
+        try
+        {
+            V3RootLevelResolver resolver = new V3RootLevelResolver(resolverContext);
+            String[] split = path.equals("/") ? new String[] {} : path.substring(1).split("/");
+            return resolver.resolve(path, split);
+        } catch (Exception e)
+        {
+            operationLog.warn(e);
+        }
+        return V3Resolver.getNonExistingFile(path, path);
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3HierarchicalContentResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3HierarchicalContentResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a1518db664fd433d4eeaa03adc04f4bc607a06f
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3HierarchicalContentResolver.java
@@ -0,0 +1,71 @@
+/*
+ * 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.LinkedList;
+import java.util.List;
+
+import org.apache.ftpserver.ftplet.FtpFile;
+
+import ch.systemsx.cisd.common.shared.basic.string.StringUtils;
+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;
+
+class V3HierarchicalContentResolver extends V3Resolver
+{
+
+    private IHierarchicalContent content;
+
+    public V3HierarchicalContentResolver(IHierarchicalContent content, FtpPathResolverContext resolverContext)
+    {
+        super(resolverContext);
+        this.content = content;
+    }
+
+    @Override
+    public FtpFile resolve(String fullPath, String[] subPath)
+    {
+        IHierarchicalContentNode rootNode;
+        if (subPath.length == 0)
+        {
+            rootNode = content.getRootNode();
+        } else
+        {
+            rootNode = content.getNode(StringUtils.join(subPath, "/"));
+        }
+
+        if (false == rootNode.isDirectory())
+        {
+            return createFileWithContent(fullPath, rootNode);
+        }
+
+        List<FtpFile> files = new LinkedList<>();
+        for (IHierarchicalContentNode node : rootNode.getChildNodes())
+        {
+            if (node.isDirectory())
+            {
+                files.add(createDirectoryScaffolding(fullPath, node.getName()));
+            } else
+            {
+                files.add(createFileScaffolding(fullPath, node.getName(), node));
+            }
+        }
+        return createDirectoryWithContent(fullPath, files);
+    }
+
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ProjectLevelResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ProjectLevelResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b28a49c0c3ddcddceb5212a1c3f253ff3b79398
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3ProjectLevelResolver.java
@@ -0,0 +1,71 @@
+/*
+ * 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.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ftpserver.ftplet.FtpFile;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.ExperimentIdentifier;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.Project;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.fetchoptions.ProjectFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.id.IProjectId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.id.ProjectIdentifier;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext;
+
+class V3ProjectLevelResolver extends V3Resolver
+{
+    private ProjectIdentifier projectIdentifier;
+
+    public V3ProjectLevelResolver(String spaceCode, String projectCode, FtpPathResolverContext resolverContext)
+    {
+        super(resolverContext);
+        this.projectIdentifier = new ProjectIdentifier(spaceCode, projectCode);
+    }
+
+    @Override
+    public FtpFile resolve(String fullPath, String[] subPath)
+    {
+        if (subPath.length == 0)
+        {
+            ProjectFetchOptions fetchOptions = new ProjectFetchOptions();
+            fetchOptions.withExperiments();
+
+            Map<IProjectId, Project> projects = api.getProjects(sessionToken, Collections.singletonList(projectIdentifier), fetchOptions);
+            Project project = projects.get(projectIdentifier);
+
+            List<FtpFile> files = new LinkedList<>();
+            for (Experiment exp : project.getExperiments())
+            {
+                files.add(createDirectoryScaffolding(fullPath, exp.getCode()));
+            }
+            return createDirectoryWithContent(fullPath, files);
+        } else
+        {
+            String item = subPath[0];
+            String[] remaining = Arrays.copyOfRange(subPath, 1, subPath.length);
+            V3ExperimentLevelResolver resolver =
+                    new V3ExperimentLevelResolver(new ExperimentIdentifier(projectIdentifier.getIdentifier() + "/" + item), resolverContext);
+            return resolver.resolve(fullPath, remaining);
+        }
+    }
+}
\ 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
new file mode 100644
index 0000000000000000000000000000000000000000..9cdb66842ad4c5c990c776537771bb7b26e90ab8
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3Resolver.java
@@ -0,0 +1,162 @@
+/*
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.ftpserver.ftplet.FtpFile;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
+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.NonExistingFtpFile;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.resolver.AbstractFtpFile;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.resolver.AbstractFtpFolder;
+
+public abstract class V3Resolver
+{
+    protected FtpPathResolverContext resolverContext;
+
+    protected IApplicationServerApi api;
+
+    protected String sessionToken;
+
+    public V3Resolver(FtpPathResolverContext resolverContext)
+    {
+        this.resolverContext = resolverContext;
+        this.sessionToken = resolverContext.getSessionToken();
+        this.api = resolverContext.getV3Api();
+    }
+
+    public abstract FtpFile resolve(String fullPath, String[] subPath);
+
+    public static FtpFile createDirectoryScaffolding(String parentPath, String name)
+    {
+        return new AbstractFtpFolder(parentPath + "/" + name)
+            {
+                @Override
+                public List<FtpFile> unsafeListFiles() throws RuntimeException
+                {
+                    throw new IllegalStateException("Don't expect to sak for file listing of scaffolding directory");
+                }
+            };
+    }
+
+    public static FtpFile createDirectoryWithContent(String name, final List<FtpFile> files)
+    {
+        return new AbstractFtpFolder(name)
+            {
+
+                @Override
+                public List<FtpFile> unsafeListFiles() throws RuntimeException
+                {
+                    return files;
+                }
+
+            };
+    }
+
+    protected FtpFile createFileWithContent(String name, final IHierarchicalContentNode node)
+    {
+        return new AbstractFtpFile(name)
+            {
+
+                @Override
+                public boolean isFile()
+                {
+                    return true;
+                }
+
+                @Override
+                public boolean isDirectory()
+                {
+                    return false;
+                }
+
+                @Override
+                public long getSize()
+                {
+                    throw new IllegalStateException("Size is not required for content node");
+                }
+
+                @Override
+                public InputStream createInputStream(long offset) throws IOException
+                {
+                    return node.getInputStream();
+                }
+
+                @Override
+                public List<FtpFile> unsafeListFiles() throws RuntimeException
+                {
+                    throw new IllegalStateException("Don't expect to sak for file listing of file");
+                }
+            };
+    }
+
+    protected FtpFile createFileScaffolding(String parentPath, String name, final IHierarchicalContentNode node)
+    {
+        return new AbstractFtpFile(parentPath + "/" + name)
+            {
+
+                @Override
+                public boolean isFile()
+                {
+                    return true;
+                }
+
+                @Override
+                public boolean isDirectory()
+                {
+                    return false;
+                }
+
+                @Override
+                public long getSize()
+                {
+                    return node.getFileLength();
+                }
+
+                @Override
+                public long getLastModified()
+                {
+                    return node.getLastModified();
+                }
+
+                @Override
+                public InputStream createInputStream(long offset) throws IOException
+                {
+                    throw new IllegalStateException("Don't expect to ask for input stream of scaffolding file");
+                }
+
+                @Override
+                public List<FtpFile> unsafeListFiles() throws RuntimeException
+                {
+                    throw new IllegalStateException("Don't expect to ask for file listing of scaffolding file");
+                }
+            };
+    }
+
+    /**
+     * Create a representation for a non-existing {@link FtpFile}, optionally providing an error message.
+     */
+    public static final FtpFile getNonExistingFile(final String path, final String errorMsgOrNull)
+    {
+        return new NonExistingFtpFile(path, errorMsgOrNull);
+    }
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3RootLevelResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3RootLevelResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e609432608456a438850f88f8735ea75eb39587
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3RootLevelResolver.java
@@ -0,0 +1,58 @@
+/*
+ * 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.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.ftpserver.ftplet.FtpFile;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.Space;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.fetchoptions.SpaceFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.search.SpaceSearchCriteria;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext;
+
+class V3RootLevelResolver extends V3Resolver
+{
+    public V3RootLevelResolver(FtpPathResolverContext resolverContext)
+    {
+        super(resolverContext);
+    }
+
+    @Override
+    public FtpFile resolve(String fullPath, String[] subPath)
+    {
+        if (subPath.length == 0)
+        {
+            List<Space> spaces =
+                    api.searchSpaces(sessionToken, new SpaceSearchCriteria(), new SpaceFetchOptions()).getObjects();
+            List<FtpFile> files = new LinkedList<>();
+            for (Space space : spaces)
+            {
+                files.add(createDirectoryScaffolding(fullPath, space.getCode()));
+            }
+            return createDirectoryWithContent(fullPath, files);
+        } else
+        {
+            String item = subPath[0];
+            String[] remaining = Arrays.copyOfRange(subPath, 1, subPath.length);
+            V3SpaceLevelResolver resolver = new V3SpaceLevelResolver(item, resolverContext);
+            return resolver.resolve(fullPath, remaining);
+        }
+    }
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3SpaceLevelResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3SpaceLevelResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..cda8e3bc9d4eb306c32f633a03618064d539f0df
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/v3/V3SpaceLevelResolver.java
@@ -0,0 +1,64 @@
+/*
+ * 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.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.ftpserver.ftplet.FtpFile;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.Project;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.fetchoptions.ProjectFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.search.ProjectSearchCriteria;
+import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext;
+
+class V3SpaceLevelResolver extends V3Resolver
+{
+    String spaceCode;
+
+    public V3SpaceLevelResolver(String spaceCode, FtpPathResolverContext resolverContext)
+    {
+        super(resolverContext);
+        this.spaceCode = spaceCode;
+    }
+
+    @Override
+    public FtpFile resolve(String fullPath, String[] subPath)
+    {
+        if (subPath.length == 0)
+        {
+            ProjectSearchCriteria searchCriteria = new ProjectSearchCriteria();
+            searchCriteria.withSpace().withCode().thatEquals(spaceCode);
+            ProjectFetchOptions fetchOptions = new ProjectFetchOptions();
+            List<Project> projects =
+                    api.searchProjects(sessionToken, searchCriteria, fetchOptions).getObjects();
+            List<FtpFile> files = new LinkedList<>();
+            for (Project project : projects)
+            {
+                files.add(V3Resolver.createDirectoryScaffolding(fullPath, project.getCode()));
+            }
+            return V3Resolver.createDirectoryWithContent(fullPath, files);
+        } else
+        {
+            String item = subPath[0];
+            String[] remaining = Arrays.copyOfRange(subPath, 1, subPath.length);
+            V3ProjectLevelResolver resolver = new V3ProjectLevelResolver(spaceCode, item, resolverContext);
+            return resolver.resolve(fullPath, remaining);
+        }
+    }
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/dssApplicationContext.xml b/datastore_server/source/java/dssApplicationContext.xml
index f88e1176d822042416992baca301a2671b457443..4434f98b5b11f8f426b11881f459f369647175c0 100644
--- a/datastore_server/source/java/dssApplicationContext.xml
+++ b/datastore_server/source/java/dssApplicationContext.xml
@@ -276,6 +276,7 @@
     <bean id="ftp-server" class="ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpServer" destroy-method="stop">
         <constructor-arg ref="etl-lims-service"/>
         <constructor-arg ref="general-information-service"/>
+        <constructor-arg ref="v3-application-service"/>
         <constructor-arg ref="adapted-ftp-user-manager"/>
     </bean>
 
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemViewTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemViewTest.java
index 154da444bd1265f6626f10440e424a42e059139f..219e706220939ce9f147c9dc25d01c6fb77df12c 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemViewTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/DSSFileSystemViewTest.java
@@ -29,6 +29,7 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.systemsx.cisd.common.test.RecordingMatcher;
 import ch.systemsx.cisd.common.test.TrackingMockery;
 import ch.systemsx.cisd.openbis.dss.generic.server.ftp.resolver.AbstractFtpFile;
@@ -48,6 +49,8 @@ public class DSSFileSystemViewTest extends AssertJUnit
 
     private IGeneralInformationService infoService;
 
+    private IApplicationServerApi v3api;
+
     private IFtpPathResolverRegistry registry;
 
     private DSSFileSystemView view;
@@ -59,8 +62,9 @@ public class DSSFileSystemViewTest extends AssertJUnit
         service = context.mock(IServiceForDataStoreServer.class);
         infoService = context.mock(IGeneralInformationService.class);
         registry = context.mock(IFtpPathResolverRegistry.class);
+        v3api = context.mock(IApplicationServerApi.class);
         prepareTryResolve("/");
-        view = new DSSFileSystemView(SESSION_TOKEN, service, infoService, registry);
+        view = new DSSFileSystemView(SESSION_TOKEN, service, infoService, v3api, registry);
     }
 
     @AfterMethod
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java
index e04dafdce3946746dae222dea29a0cc1db9d76d7..35e10507c0438f4bd0e751b7d5564d29eefcf3a9 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java
@@ -35,6 +35,7 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.rinn.restrictions.Friend;
 import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase;
 import ch.systemsx.cisd.common.action.IDelegatedAction;
@@ -164,6 +165,8 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem
 
     private IGeneralInformationService generalInfoService;
 
+    private IApplicationServerApi v3api;
+
     private SimpleFileContentProvider simpleFileContentProvider;
 
     private PhysicalDataSet ds1;
@@ -192,6 +195,7 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem
         context = new TrackingMockery();
         service = context.mock(IServiceForDataStoreServer.class);
         generalInfoService = context.mock(IGeneralInformationService.class);
+        v3api = context.mock(IApplicationServerApi.class);
 
         hierarchicalContentProvider = context.mock(IHierarchicalContentProvider.class);
         File root = new File(workingDirectory, "data-sets");
@@ -199,7 +203,7 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem
         simpleFileContentProvider = new SimpleFileContentProvider(root);
 
         resolverContext =
-                new FtpPathResolverContext(SESSION_TOKEN, service, generalInfoService, null,
+                new FtpPathResolverContext(SESSION_TOKEN, service, generalInfoService, v3api, null,
                         new Cache(timeProvider));
         context.checking(new Expectations()
             {