diff --git a/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContent.java b/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContent.java
index 3b397d60d7efc514135cf497439f7d0e8ab85eee..8132da599f80da71b4820eb1326f7c5c4ea162e1 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContent.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContent.java
@@ -95,8 +95,7 @@ class DefaultFileBasedHierarchicalContent implements IHierarchicalContent
         if (existingFile != null && FileUtilities.isHDF5ContainerFile(existingFile))
         {
             HDF5ContainerBasedHierarchicalContentNode containerNode =
-                    new HDF5ContainerBasedHierarchicalContentNode(hierarchicalContentFactory, this,
-                            existingFile);
+                    new HDF5ContainerBasedHierarchicalContentNode(this, existingFile);
             String relativePath = FileUtilities.getRelativeFile(existingFile, file);
             return containerNode.getChildNode(relativePath);
         }
diff --git a/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentFactory.java b/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentFactory.java
index f418400406e0aac76e3794d31b1a489538cb1337..79d1a54fe1d6f8e681874e0e461ddab03af3efa7 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentFactory.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentFactory.java
@@ -39,7 +39,7 @@ public class DefaultFileBasedHierarchicalContentFactory implements IHierarchical
     {
         if (FileUtilities.isHDF5ContainerFile(file))
         {
-            return new HDF5ContainerBasedHierarchicalContentNode(this, rootContent, file);
+            return new HDF5ContainerBasedHierarchicalContentNode(rootContent, file);
         }
         return new DefaultFileBasedHierarchicalContentNode(this, rootContent, file);
     }
diff --git a/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentNode.java
index 4cf025088bf96de8893532dc794664c973d9de3d..9618ae7bde42614f6aa5a411e4abbec76a10b81b 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/DefaultFileBasedHierarchicalContentNode.java
@@ -39,16 +39,20 @@ class DefaultFileBasedHierarchicalContentNode extends AbstractHierarchicalConten
 
     protected final File file;
 
-    protected final IHierarchicalContentFactory hierarchicalContentFactory;
+    private final IHierarchicalContentFactory hierarchicalContentFactoryOrNull;
+
+    protected DefaultFileBasedHierarchicalContentNode(IHierarchicalContent root, File file)
+    {
+        this(null, root, file);
+    }
 
     protected DefaultFileBasedHierarchicalContentNode(
-            IHierarchicalContentFactory hierarchicalContentFactory, IHierarchicalContent root,
-            File file)
+            IHierarchicalContentFactory hierarchicalContentFactoryOrNull,
+            IHierarchicalContent root, File file)
     {
-        assert hierarchicalContentFactory != null;
         assert root != null;
         assert file != null;
-        this.hierarchicalContentFactory = hierarchicalContentFactory;
+        this.hierarchicalContentFactoryOrNull = hierarchicalContentFactoryOrNull;
         this.root = root;
         this.file = file;
     }
@@ -82,13 +86,16 @@ class DefaultFileBasedHierarchicalContentNode extends AbstractHierarchicalConten
     @Override
     public List<IHierarchicalContentNode> doGetChildNodes()
     {
+        // if factory is not defined the method should be overriden
+        assert hierarchicalContentFactoryOrNull != null;
+
         File[] files = file.listFiles();
         List<IHierarchicalContentNode> result = new ArrayList<IHierarchicalContentNode>();
         if (files != null)
         {
             for (File aFile : files)
             {
-                result.add(hierarchicalContentFactory.asHierarchicalContentNode(root, aFile));
+                result.add(hierarchicalContentFactoryOrNull.asHierarchicalContentNode(root, aFile));
             }
         }
         return result;
diff --git a/common/source/java/ch/systemsx/cisd/common/io/HDF5ContainerBasedHierarchicalContentNode.java b/common/source/java/ch/systemsx/cisd/common/io/HDF5ContainerBasedHierarchicalContentNode.java
index 4cdc0ce53551c3e496199f975751a9767936eb01..e870f861fdf76615b0d2deace7730b2ac8fa85d8 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/HDF5ContainerBasedHierarchicalContentNode.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/HDF5ContainerBasedHierarchicalContentNode.java
@@ -31,15 +31,15 @@ import ch.systemsx.cisd.hdf5.IHDF5SimpleReader;
  * 
  * @author Piotr Buczek
  */
-class HDF5ContainerBasedHierarchicalContentNode extends DefaultFileBasedHierarchicalContentNode
+public class HDF5ContainerBasedHierarchicalContentNode extends
+        DefaultFileBasedHierarchicalContentNode
 {
     private final Hdf5Container hdf5Container;
 
-    HDF5ContainerBasedHierarchicalContentNode(
-            IHierarchicalContentFactory hierarchicalContentFactory, IHierarchicalContent root,
+    public HDF5ContainerBasedHierarchicalContentNode(IHierarchicalContent root,
             File hdf5ContainerFile)
     {
-        super(hierarchicalContentFactory, root, hdf5ContainerFile);
+        super(root, hdf5ContainerFile);
         this.hdf5Container = new Hdf5Container(hdf5ContainerFile);
     }
 
@@ -59,7 +59,6 @@ class HDF5ContainerBasedHierarchicalContentNode extends DefaultFileBasedHierarch
     @Override
     public List<IHierarchicalContentNode> doGetChildNodes()
     {
-        // NOTE this is a slow implementation - improve it when information can be retrieved from DB
         IHDF5SimpleReader reader = createReader();
         try
         {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISingleDataSetPathInfoProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISingleDataSetPathInfoProvider.java
index 71041ff246832d776ced4bcb4f61db232e807c20..469633d56106dcf07330cbf6b16f87ae89e0fb88 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISingleDataSetPathInfoProvider.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISingleDataSetPathInfoProvider.java
@@ -31,6 +31,8 @@ public interface ISingleDataSetPathInfoProvider
 
     DataSetPathInfo tryGetPathInfoByRelativePath(String relativePath);
 
+    // DataSetPathInfo getParentPathInfo(DataSetPathInfo child);
+
     List<DataSetPathInfo> listChildrenPathInfos(DataSetPathInfo parent);
 
     List<DataSetPathInfo> listMatchingPathInfos(String relativePathPattern);
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java
index 802b95dce2f4f0ed0963aad9c7635515624efe0f..1e7c62e86cfed361b8de5a3a39829dbf77bcbe97 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/content/PathInfoProviderBasedHierarchicalContent.java
@@ -26,7 +26,9 @@ import java.util.List;
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.base.io.IRandomAccessFile;
 import ch.systemsx.cisd.base.io.RandomAccessFileImpl;
+import ch.systemsx.cisd.common.filesystem.FileUtilities;
 import ch.systemsx.cisd.common.io.AbstractHierarchicalContentNode;
+import ch.systemsx.cisd.common.io.HDF5ContainerBasedHierarchicalContentNode;
 import ch.systemsx.cisd.common.io.IHierarchicalContent;
 import ch.systemsx.cisd.common.io.IHierarchicalContentNode;
 import ch.systemsx.cisd.common.shared.basic.utils.StringUtils;
@@ -93,7 +95,7 @@ class PathInfoProviderBasedHierarchicalContent implements IHierarchicalContent
 
     private IHierarchicalContentNode asNode(DataSetPathInfo pathInfo)
     {
-        return new PathInfoNode(pathInfo, root, dataSetPathInfoProvider);
+        return new PathInfoNode(pathInfo);
     }
 
     private DataSetPathInfo findPathInfo(String relativePath) throws IllegalArgumentException
@@ -187,21 +189,15 @@ class PathInfoProviderBasedHierarchicalContent implements IHierarchicalContent
         return true;
     }
 
-    static class PathInfoNode extends AbstractHierarchicalContentNode
+    class PathInfoNode extends AbstractHierarchicalContentNode
     {
-
         private final DataSetPathInfo pathInfo;
 
-        private final File root;
-
-        private final ISingleDataSetPathInfoProvider dataSetPathInfoProvider;
+        private IFileContentProvider fileContentProviderOrNull;
 
-        PathInfoNode(DataSetPathInfo pathInfo, File root,
-                ISingleDataSetPathInfoProvider dataSetPathInfoProvider)
+        PathInfoNode(DataSetPathInfo pathInfo)
         {
             this.pathInfo = pathInfo;
-            this.root = root;
-            this.dataSetPathInfoProvider = dataSetPathInfoProvider;
         }
 
         public String getName()
@@ -233,7 +229,7 @@ class PathInfoProviderBasedHierarchicalContent implements IHierarchicalContent
             List<IHierarchicalContentNode> result = new ArrayList<IHierarchicalContentNode>();
             for (DataSetPathInfo child : pathInfos)
             {
-                result.add(new PathInfoNode(child, root, dataSetPathInfoProvider));
+                result.add(asNode(child));
             }
             return result;
         }
@@ -244,37 +240,130 @@ class PathInfoProviderBasedHierarchicalContent implements IHierarchicalContent
             return pathInfo.getSizeInBytes();
         }
 
-        // TODO 2011-04-19, Piotr Buczek: use abstraction to get file content
-
         public File getFile() throws UnsupportedOperationException
         {
-            if (StringUtils.isBlank(getRelativePath()))
+            File result = doGetFile();
+            if (result.exists())
             {
-                return root;
+                return result;
             } else
             {
-                return new File(root, getRelativePath());
+                throw new UnsupportedOperationException("This is not a normal file/directory node.");
             }
         }
 
         @Override
         protected IRandomAccessFile doGetFileContent()
         {
-            return new RandomAccessFileImpl(getFile(), "r");
+            return getFileContentProvider().getReadOnlyRandomAccessFile();
         }
 
         @Override
         protected InputStream doGetInputStream()
         {
-            try
+            return getFileContentProvider().getInputStream();
+        }
+
+        private IFileContentProvider getFileContentProvider()
+        {
+            if (fileContentProviderOrNull == null)
+            {
+                File file = doGetFile();
+                fileContentProviderOrNull = getContent(file);
+            }
+            return fileContentProviderOrNull;
+        }
+
+        /**
+         * Returns a file object with given node's relative path. The file doesn't have to exist on
+         * the file system.
+         */
+        private File doGetFile()
+        {
+            if (StringUtils.isBlank(getRelativePath()))
             {
-                return new FileInputStream(getFile());
-            } catch (FileNotFoundException ex)
+                return root;
+            } else
             {
-                throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+                return new File(root, getRelativePath());
             }
         }
+    }
+
+    private IFileContentProvider getContent(File file)
+    {
+        if (file.exists())
+        {
+            return asFileContentProvider(file);
+        }
+
+        // The file doesn't exist in file system but it could be inside a HDF5 container.
+        // Go up in file hierarchy until existing file is found.
+        File existingFile = file;
+        while (existingFile != null && existingFile.exists() == false)
+        {
+            existingFile = existingFile.getParentFile();
+        }
+        if (existingFile != null && FileUtilities.isHDF5ContainerFile(existingFile))
+        {
+            HDF5ContainerBasedHierarchicalContentNode containerNode =
+                    new HDF5ContainerBasedHierarchicalContentNode(this, existingFile);
+            String relativePath = FileUtilities.getRelativeFile(existingFile, file);
+            IHierarchicalContentNode node = containerNode.getChildNode(relativePath);
+            return asFileContentProvider(node);
+        }
+        throw new IllegalArgumentException("Resource '" + FileUtilities.getRelativeFile(root, file)
+                + "' does not exist.");
+    }
+
+    private interface IFileContentProvider
+    {
+        public IRandomAccessFile getReadOnlyRandomAccessFile();
+
+        public InputStream getInputStream();
+    }
+
+    private static IFileContentProvider asFileContentProvider(final File existingFile)
+    {
+        assert existingFile.exists();
+        return new IFileContentProvider()
+            {
+
+                public IRandomAccessFile getReadOnlyRandomAccessFile()
+                {
+                    return new RandomAccessFileImpl(existingFile, "r");
+                }
+
+                public InputStream getInputStream()
+                {
+                    try
+                    {
+                        return new FileInputStream(existingFile);
+                    } catch (FileNotFoundException ex)
+                    {
+                        throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+                    }
+                }
+
+            };
+    }
+
+    private static IFileContentProvider asFileContentProvider(final IHierarchicalContentNode node)
+    {
+        return new IFileContentProvider()
+            {
+
+                public IRandomAccessFile getReadOnlyRandomAccessFile()
+                {
+                    return node.getFileContent();
+                }
+
+                public InputStream getInputStream()
+                {
+                    return node.getInputStream();
+                }
 
+            };
     }
 
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetPathInfo.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetPathInfo.java
index dd4045a5838dd84093507453a9a7d6f9036ae93b..3544dc7fea2793c0bf0e3df98d8236b0d37efe52 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetPathInfo.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/DataSetPathInfo.java
@@ -78,6 +78,7 @@ public class DataSetPathInfo
         this.sizeInBytes = sizeInBytes;
     }
 
+    @Deprecated
     public DataSetPathInfo getParent()
     {
         return parent;
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java
index 3d23d3e984f3c10853d0ca78348d22ebb2a63996..82492d9e123794a5d2ea5608907e2a242ee3e912 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java
@@ -167,6 +167,7 @@ public class DatabaseBasedDataSetPathInfoProviderTest extends AssertJUnit
         assertEquals(2, list.size());
     }
 
+    @SuppressWarnings("deprecation")
     private void check(String expectedRelativePath, String expectedFileName,
             boolean expectingDirectory, long expectedSize, DataSetPathInfo info)
     {
@@ -174,7 +175,6 @@ public class DatabaseBasedDataSetPathInfoProviderTest extends AssertJUnit
         assertEquals(expectedFileName, info.getFileName());
         assertEquals(expectingDirectory, info.isDirectory());
         assertEquals(expectedSize, info.getSizeInBytes());
-        @SuppressWarnings("deprecation")
         List<DataSetPathInfo> children = info.getChildren();
         for (DataSetPathInfo child : children)
         {