Adding functionality into the MetadataCollector to list directories and browse files
diff --git a/agent/src/main/java/org/apache/airavata/mft/agent/TransportMediator.java b/agent/src/main/java/org/apache/airavata/mft/agent/TransportMediator.java
index d8a2ebe..cd90503 100644
--- a/agent/src/main/java/org/apache/airavata/mft/agent/TransportMediator.java
+++ b/agent/src/main/java/org/apache/airavata/mft/agent/TransportMediator.java
@@ -28,7 +28,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Optional;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.ReentrantLock;
@@ -53,7 +52,7 @@
                            MetadataCollector destMetadataCollector, BiConsumer<String, TransferState> onStatusCallback,
                            BiConsumer<String, Boolean> exitingCallback) throws Exception {
 
-        ResourceMetadata srcMetadata = srcMetadataCollector.getGetResourceMetadata(command.getSourceId(), command.getSourceToken());
+        FileResourceMetadata srcMetadata = srcMetadataCollector.getFileResourceMetadata(command.getSourceId(), command.getSourceToken());
 
         final long resourceSize = srcMetadata.getResourceSize();
         logger.debug("Source file size {}. MD5 {}", resourceSize, srcMetadata.getMd5sum());
@@ -129,7 +128,7 @@
                             throw new Exception("Transfer completed but resource is not available in destination");
                         }
 
-                        ResourceMetadata destMetadata = destMetadataCollector.getGetResourceMetadata(command.getDestinationId(),
+                        FileResourceMetadata destMetadata = destMetadataCollector.getFileResourceMetadata(command.getDestinationId(),
                                 command.getDestinationToken());
 
                         boolean doIntegrityVerify = true;
diff --git a/core/src/main/java/org/apache/airavata/mft/core/ConnectorContext.java b/core/src/main/java/org/apache/airavata/mft/core/ConnectorContext.java
index a4cd805..c8ce64f 100644
--- a/core/src/main/java/org/apache/airavata/mft/core/ConnectorContext.java
+++ b/core/src/main/java/org/apache/airavata/mft/core/ConnectorContext.java
@@ -20,7 +20,7 @@
 public class ConnectorContext {
 
     private DoubleStreamingBuffer streamBuffer;
-    private ResourceMetadata metadata;
+    private FileResourceMetadata metadata;
     private String transferId;
 
     public DoubleStreamingBuffer getStreamBuffer() {
@@ -31,11 +31,11 @@
         this.streamBuffer = streamBuffer;
     }
 
-    public ResourceMetadata getMetadata() {
+    public FileResourceMetadata getMetadata() {
         return metadata;
     }
 
-    public void setMetadata(ResourceMetadata metadata) {
+    public void setMetadata(FileResourceMetadata metadata) {
         this.metadata = metadata;
     }
 
diff --git a/core/src/main/java/org/apache/airavata/mft/core/DirectoryResourceMetadata.java b/core/src/main/java/org/apache/airavata/mft/core/DirectoryResourceMetadata.java
new file mode 100644
index 0000000..5eb9813
--- /dev/null
+++ b/core/src/main/java/org/apache/airavata/mft/core/DirectoryResourceMetadata.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.airavata.mft.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DirectoryResourceMetadata {
+
+    private String friendlyName;
+    private long createdTime;
+    private long updateTime;
+    private String resourcePath;
+    private String parentResourceId;
+    private String parentResourceType;
+    private List<DirectoryResourceMetadata> directories = new ArrayList<>();
+    private List<FileResourceMetadata> files = new ArrayList<>();
+    private boolean lazyInitialized = true;
+
+    public String getFriendlyName() {
+        return friendlyName;
+    }
+
+    public DirectoryResourceMetadata setFriendlyName(String friendlyName) {
+        this.friendlyName = friendlyName;
+        return this;
+    }
+
+    public long getCreatedTime() {
+        return createdTime;
+    }
+
+    public DirectoryResourceMetadata setCreatedTime(long createdTime) {
+        this.createdTime = createdTime;
+        return this;
+    }
+
+    public long getUpdateTime() {
+        return updateTime;
+    }
+
+    public DirectoryResourceMetadata setUpdateTime(long updateTime) {
+        this.updateTime = updateTime;
+        return this;
+    }
+
+    public String getResourcePath() {
+        return resourcePath;
+    }
+
+    public DirectoryResourceMetadata setResourcePath(String resourcePath) {
+        this.resourcePath = resourcePath;
+        return this;
+    }
+
+    public String getParentResourceId() {
+        return parentResourceId;
+    }
+
+    public DirectoryResourceMetadata setParentResourceId(String parentResourceId) {
+        this.parentResourceId = parentResourceId;
+        return this;
+    }
+
+    public String getParentResourceType() {
+        return parentResourceType;
+    }
+
+    public DirectoryResourceMetadata setParentResourceType(String parentResourceType) {
+        this.parentResourceType = parentResourceType;
+        return this;
+    }
+
+    public List<DirectoryResourceMetadata> getDirectories() {
+        return directories;
+    }
+
+    public DirectoryResourceMetadata setDirectories(List<DirectoryResourceMetadata> directories) {
+        this.directories = directories;
+        return this;
+    }
+
+    public List<FileResourceMetadata> getFiles() {
+        return files;
+    }
+
+    public DirectoryResourceMetadata setFiles(List<FileResourceMetadata> files) {
+        this.files = files;
+        return this;
+    }
+
+    public boolean isLazyInitialized() {
+        return lazyInitialized;
+    }
+
+    public DirectoryResourceMetadata setLazyInitialized(boolean lazyInitialized) {
+        this.lazyInitialized = lazyInitialized;
+        return this;
+    }
+
+
+    public static final class Builder {
+        private String friendlyName;
+        private long createdTime;
+        private long updateTime;
+        private String resourcePath;
+        private String parentResourceId;
+        private String parentResourceType;
+        private List<DirectoryResourceMetadata> directories = new ArrayList<>();
+        private List<FileResourceMetadata> files = new ArrayList<>();
+        private boolean lazyInitialized = true;
+
+        private Builder() {
+        }
+
+        public static Builder getBuilder() {
+            return new Builder();
+        }
+
+        public Builder withFriendlyName(String friendlyName) {
+            this.friendlyName = friendlyName;
+            return this;
+        }
+
+        public Builder withCreatedTime(long createdTime) {
+            this.createdTime = createdTime;
+            return this;
+        }
+
+        public Builder withUpdateTime(long updateTime) {
+            this.updateTime = updateTime;
+            return this;
+        }
+
+        public Builder withResourcePath(String resourcePath) {
+            this.resourcePath = resourcePath;
+            return this;
+        }
+
+        public Builder withParentResourceId(String parentResourceId) {
+            this.parentResourceId = parentResourceId;
+            return this;
+        }
+
+        public Builder withParentResourceType(String parentResourceType) {
+            this.parentResourceType = parentResourceType;
+            return this;
+        }
+
+        public Builder withDirectories(List<DirectoryResourceMetadata> directories) {
+            this.directories = directories;
+            return this;
+        }
+
+        public Builder withDirectory(DirectoryResourceMetadata directory) {
+            this.directories.add(directory);
+            return this;
+        }
+
+        public Builder withFiles(List<FileResourceMetadata> files) {
+            this.files = files;
+            return this;
+        }
+
+        public Builder withFile(FileResourceMetadata file) {
+            this.files.add(file);
+            return this;
+        }
+
+        public Builder withLazyInitialized(boolean lazyInitialized) {
+            this.lazyInitialized = lazyInitialized;
+            return this;
+        }
+
+        public DirectoryResourceMetadata build() {
+            DirectoryResourceMetadata directoryResourceMetadata = new DirectoryResourceMetadata();
+            directoryResourceMetadata.setFriendlyName(friendlyName);
+            directoryResourceMetadata.setCreatedTime(createdTime);
+            directoryResourceMetadata.setUpdateTime(updateTime);
+            directoryResourceMetadata.setResourcePath(resourcePath);
+            directoryResourceMetadata.setParentResourceId(parentResourceId);
+            directoryResourceMetadata.setParentResourceType(parentResourceType);
+            directoryResourceMetadata.setDirectories(directories);
+            directoryResourceMetadata.setFiles(files);
+            directoryResourceMetadata.setLazyInitialized(lazyInitialized);
+            return directoryResourceMetadata;
+        }
+    }
+}
diff --git a/core/src/main/java/org/apache/airavata/mft/core/FileResourceMetadata.java b/core/src/main/java/org/apache/airavata/mft/core/FileResourceMetadata.java
new file mode 100644
index 0000000..0b2372e
--- /dev/null
+++ b/core/src/main/java/org/apache/airavata/mft/core/FileResourceMetadata.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.airavata.mft.core;
+
+public class FileResourceMetadata {
+
+    private String friendlyName;
+    private long resourceSize;
+    private long createdTime;
+    private long updateTime;
+    private String md5sum;
+    private String resourcePath;
+    private String parentResourceId;
+    private String parentResourceType;
+
+    public String getFriendlyName() {
+        return friendlyName;
+    }
+
+    public FileResourceMetadata setFriendlyName(String friendlyName) {
+        this.friendlyName = friendlyName;
+        return this;
+    }
+
+    public long getResourceSize() {
+        return resourceSize;
+    }
+
+    public FileResourceMetadata setResourceSize(long resourceSize) {
+        this.resourceSize = resourceSize;
+        return this;
+    }
+
+    public long getCreatedTime() {
+        return createdTime;
+    }
+
+    public FileResourceMetadata setCreatedTime(long createdTime) {
+        this.createdTime = createdTime;
+        return this;
+    }
+
+    public long getUpdateTime() {
+        return updateTime;
+    }
+
+    public FileResourceMetadata setUpdateTime(long updateTime) {
+        this.updateTime = updateTime;
+        return this;
+    }
+
+    public String getMd5sum() {
+        return md5sum;
+    }
+
+    public FileResourceMetadata setMd5sum(String md5sum) {
+        this.md5sum = md5sum;
+        return this;
+    }
+
+    public String getResourcePath() {
+        return resourcePath;
+    }
+
+    public FileResourceMetadata setResourcePath(String resourcePath) {
+        this.resourcePath = resourcePath;
+        return this;
+    }
+
+    public String getParentResourceId() {
+        return parentResourceId;
+    }
+
+    public FileResourceMetadata setParentResourceId(String parentResourceId) {
+        this.parentResourceId = parentResourceId;
+        return this;
+    }
+
+    public String getParentResourceType() {
+        return parentResourceType;
+    }
+
+    public FileResourceMetadata setParentResourceType(String parentResourceType) {
+        this.parentResourceType = parentResourceType;
+        return this;
+    }
+
+    public static final class Builder {
+        private String friendlyName;
+        private long resourceSize;
+        private long createdTime;
+        private long updateTime;
+        private String md5sum;
+        private String resourcePath;
+        private String parentResourceId;
+        private String parentResourceType;
+
+        private Builder() {
+        }
+
+        public static Builder getBuilder() {
+            return new Builder();
+        }
+
+        public Builder withFriendlyName(String friendlyName) {
+            this.friendlyName = friendlyName;
+            return this;
+        }
+
+        public Builder withResourceSize(long resourceSize) {
+            this.resourceSize = resourceSize;
+            return this;
+        }
+
+        public Builder withCreatedTime(long createdTime) {
+            this.createdTime = createdTime;
+            return this;
+        }
+
+        public Builder withUpdateTime(long updateTime) {
+            this.updateTime = updateTime;
+            return this;
+        }
+
+        public Builder withMd5sum(String md5sum) {
+            this.md5sum = md5sum;
+            return this;
+        }
+
+        public Builder withResourcePath(String resourcePath) {
+            this.resourcePath = resourcePath;
+            return this;
+        }
+
+        public Builder withParentResourceId(String parentResourceId) {
+            this.parentResourceId = parentResourceId;
+            return this;
+        }
+
+        public Builder withParentResourceType(String parentResourceType) {
+            this.parentResourceType = parentResourceType;
+            return this;
+        }
+
+        public FileResourceMetadata build() {
+            FileResourceMetadata fileResourceMetadata = new FileResourceMetadata();
+            fileResourceMetadata.setFriendlyName(friendlyName);
+            fileResourceMetadata.setResourceSize(resourceSize);
+            fileResourceMetadata.setCreatedTime(createdTime);
+            fileResourceMetadata.setUpdateTime(updateTime);
+            fileResourceMetadata.setMd5sum(md5sum);
+            fileResourceMetadata.setResourcePath(resourcePath);
+            fileResourceMetadata.setParentResourceId(parentResourceId);
+            fileResourceMetadata.setParentResourceType(parentResourceType);
+            return fileResourceMetadata;
+        }
+    }
+}
diff --git a/core/src/main/java/org/apache/airavata/mft/core/ResourceMetadata.java b/core/src/main/java/org/apache/airavata/mft/core/ResourceMetadata.java
deleted file mode 100644
index 378153b..0000000
--- a/core/src/main/java/org/apache/airavata/mft/core/ResourceMetadata.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.airavata.mft.core;
-
-public class ResourceMetadata {
-
-    private long resourceSize;
-    private long createdTime;
-    private long updateTime;
-    private String md5sum;
-
-    public long getResourceSize() {
-        return resourceSize;
-    }
-
-    public void setResourceSize(long resourceSize) {
-        this.resourceSize = resourceSize;
-    }
-
-    public long getCreatedTime() {
-        return createdTime;
-    }
-
-    public void setCreatedTime(long createdTime) {
-        this.createdTime = createdTime;
-    }
-
-    public long getUpdateTime() {
-        return updateTime;
-    }
-
-    public void setUpdateTime(long updateTime) {
-        this.updateTime = updateTime;
-    }
-
-    public String getMd5sum() {
-        return md5sum;
-    }
-
-    public void setMd5sum(String md5sum) {
-        this.md5sum = md5sum;
-    }
-}
diff --git a/core/src/main/java/org/apache/airavata/mft/core/api/MetadataCollector.java b/core/src/main/java/org/apache/airavata/mft/core/api/MetadataCollector.java
index c8e4fc4..e784867 100644
--- a/core/src/main/java/org/apache/airavata/mft/core/api/MetadataCollector.java
+++ b/core/src/main/java/org/apache/airavata/mft/core/api/MetadataCollector.java
@@ -17,10 +17,74 @@
 
 package org.apache.airavata.mft.core.api;
 
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 
 public interface MetadataCollector {
+
+    /**
+     * Initializes the {@link MetadataCollector}
+     *
+     * @param resourceServiceHost hostname of the resource service
+     * @param resourceServicePort port of the resource service
+     * @param secretServiceHost hostname of the secret service
+     * @param secretServicePort port of the secret service
+     */
     public void init(String resourceServiceHost, int resourceServicePort, String secretServiceHost, int secretServicePort);
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws Exception;
+
+    /**
+     * Fetches a metadata of given File Resource
+     *
+     * @param resourceId id of the resource
+     * @param credentialToken credential token for the resource
+     * @return an object of {@link FileResourceMetadata}
+     * @throws Exception if the resource id is not a File Resource type or the resource can't be fetched from the resource service
+     */
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception;
+
+    /**
+     * Fetches a metadata of given File Resource inside a registered directory resource. Target file might be living in
+     * multiple level below the parent directory
+     *
+     * @param parentResourceId parent directory resource id
+     * @param resourcePath path of the target resource. This should be a child path of the parent resource
+     * @param credentialToken credential token for the resource
+     * @return an object of {@link FileResourceMetadata}
+     * @throws Exception if the parent resource is not a Directory resource or the target resource is not a File Resource type
+     * or the resource can't be fetched from the resource service
+     */
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception;
+
+    /**
+     * Fetches a metadata of given Directory Resource
+     *
+     * @param resourceId id of the resource
+     * @param credentialToken credential token for the resource
+     * @return an object of {@link DirectoryResourceMetadata}
+     * @throws Exception if the resource id is not a Directory Resource type or the resource can't be fetched from the resource service
+     */
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception;
+
+    /**
+     * Fetches a metadata of given Directory Resource inside a registered directory resource. Target directory might be living in
+     * multiple level below the parent directory
+     *
+     * @param parentResourceId parent directory resource id
+     * @param resourcePath path of the target resource. This should be a child path of the parent resource
+     * @param credentialToken credential token for the resource
+     * @return an object of {@link DirectoryResourceMetadata}
+     * @throws Exception if the parent resource is not a Directory resource or the target resource is not a Directory Resource type
+     * or the resource can't be fetched from the resource service
+     */
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception;
+
+    /**
+     * Check whether the resource is available in the actual storage
+     *
+     * @param resourceId id of the resource
+     * @param credentialToken credential token for the resource
+     * @return true of the resource is available false otherwise
+     * @throws Exception if the resource details can not be fetched from the resource service
+     */
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception;
 }
diff --git a/services/resource-service/server/src/main/resources/resources.json b/services/resource-service/server/src/main/resources/resources.json
index 83e009f..a389282 100644
--- a/services/resource-service/server/src/main/resources/resources.json
+++ b/services/resource-service/server/src/main/resources/resources.json
@@ -1,6 +1,18 @@
 [
   {
     "type": "SCP",
+    "resourceId":  "remote-ssh-dir-resource",
+    "resourceMode": "DIRECTORY",
+    "resourcePath": "/tmp",
+    "scpStorage" : {
+      "storageId": "remote-ssh-storage",
+      "host": "149.165.156.124",
+      "port": 22,
+      "user": "root"
+    }
+  },
+  {
+    "type": "SCP",
     "resourceId":  "remote-ssh-resource",
     "resourceMode": "FILE",
     "resourcePath": "/tmp/1mb.txt",
diff --git a/transport/azure-transport/src/main/java/org/apache/airavata/mft/transport/azure/AzureMetadataCollector.java b/transport/azure-transport/src/main/java/org/apache/airavata/mft/transport/azure/AzureMetadataCollector.java
index 8a265c8..5a64d54 100644
--- a/transport/azure-transport/src/main/java/org/apache/airavata/mft/transport/azure/AzureMetadataCollector.java
+++ b/transport/azure-transport/src/main/java/org/apache/airavata/mft/transport/azure/AzureMetadataCollector.java
@@ -22,7 +22,8 @@
 import com.azure.storage.blob.BlobServiceClient;
 import com.azure.storage.blob.BlobServiceClientBuilder;
 import com.azure.storage.blob.models.BlobProperties;
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.credential.stubs.azure.AzureSecret;
@@ -58,7 +59,7 @@
     }
 
     @Override
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws Exception {
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception {
         checkInitialized();
 
         if (!isAvailable(resourceId, credentialToken)) {
@@ -77,7 +78,7 @@
                                                 .getBlobClient(azureResource.getFile().getResourcePath());
 
         BlobProperties properties = blobClient.getBlockBlobClient().getProperties();
-        ResourceMetadata metadata = new ResourceMetadata();
+        FileResourceMetadata metadata = new FileResourceMetadata();
         metadata.setResourceSize(properties.getBlobSize());
         metadata.setCreatedTime(properties.getCreationTime().toEpochSecond());
         metadata.setUpdateTime(properties.getCreationTime().toEpochSecond());
@@ -94,6 +95,20 @@
     }
 
     @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception {
         checkInitialized();
 
diff --git a/transport/box-transport/src/main/java/org/apache/airavata/mft/transport/box/BoxMetadataCollector.java b/transport/box-transport/src/main/java/org/apache/airavata/mft/transport/box/BoxMetadataCollector.java
index b55a0f2..8e21c9f 100644
--- a/transport/box-transport/src/main/java/org/apache/airavata/mft/transport/box/BoxMetadataCollector.java
+++ b/transport/box-transport/src/main/java/org/apache/airavata/mft/transport/box/BoxMetadataCollector.java
@@ -20,7 +20,8 @@
 
 import com.box.sdk.BoxAPIConnection;
 import com.box.sdk.BoxFile;
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.credential.stubs.box.BoxSecret;
@@ -56,7 +57,7 @@
     }
 
     @Override
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws Exception {
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception {
 
         checkInitialized();
 
@@ -70,7 +71,7 @@
         BoxFile boxFile = new BoxFile(api, boxResource.getFile().getResourcePath());
         BoxFile.Info boxFileInfo = boxFile.getInfo();
 
-        ResourceMetadata metadata = new ResourceMetadata();
+        FileResourceMetadata metadata = new FileResourceMetadata();
         metadata.setResourceSize(boxFileInfo.getSize());
 
         // TODO
@@ -83,6 +84,20 @@
     }
 
     @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception {
 
         checkInitialized();
diff --git a/transport/dropbox-transport/src/main/java/org/apache/airavata/mft/transport/dropbox/DropboxMetadataCollector.java b/transport/dropbox-transport/src/main/java/org/apache/airavata/mft/transport/dropbox/DropboxMetadataCollector.java
index 1310c53..906fb0b 100644
--- a/transport/dropbox-transport/src/main/java/org/apache/airavata/mft/transport/dropbox/DropboxMetadataCollector.java
+++ b/transport/dropbox-transport/src/main/java/org/apache/airavata/mft/transport/dropbox/DropboxMetadataCollector.java
@@ -20,7 +20,8 @@
 import com.dropbox.core.DbxRequestConfig;
 import com.dropbox.core.v2.DbxClientV2;
 import com.dropbox.core.v2.files.FileMetadata;
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.credential.stubs.dropbox.DropboxSecret;
@@ -55,9 +56,8 @@
         }
     }
 
-
     @Override
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws Exception {
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception {
         checkInitialized();
         ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
         DropboxResource dropboxResource = resourceClient.dropbox().getDropboxResource(DropboxResourceGetRequest.newBuilder().setResourceId(resourceId).build());
@@ -68,7 +68,7 @@
         DbxRequestConfig config = DbxRequestConfig.newBuilder("mftdropbox/v1").build();
         DbxClientV2 dbxClientV2 = new DbxClientV2(config, dropboxSecret.getAccessToken());
 
-        ResourceMetadata metadata = new ResourceMetadata();
+        FileResourceMetadata metadata = new FileResourceMetadata();
         FileMetadata fileMetadata = (FileMetadata) dbxClientV2.files().getMetadata(dropboxResource.getFile().getResourcePath());
         metadata.setResourceSize(fileMetadata.getSize());
         metadata.setMd5sum(null);
@@ -78,6 +78,20 @@
     }
 
     @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception {
         checkInitialized();
         ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
diff --git a/transport/ftp-transport/src/main/java/org/apache/airavata/mft/transport/ftp/FTPMetadataCollector.java b/transport/ftp-transport/src/main/java/org/apache/airavata/mft/transport/ftp/FTPMetadataCollector.java
index 9b71dc8..66675f3 100644
--- a/transport/ftp-transport/src/main/java/org/apache/airavata/mft/transport/ftp/FTPMetadataCollector.java
+++ b/transport/ftp-transport/src/main/java/org/apache/airavata/mft/transport/ftp/FTPMetadataCollector.java
@@ -17,7 +17,8 @@
 
 package org.apache.airavata.mft.transport.ftp;
 
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.credential.stubs.ftp.FTPSecret;
@@ -62,7 +63,7 @@
     }
 
     @Override
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) {
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) {
 
         checkInitialized();
         ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
@@ -70,7 +71,7 @@
         SecretServiceClient secretClient = SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
         FTPSecret ftpSecret = secretClient.ftp().getFTPSecret(FTPSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
 
-        ResourceMetadata resourceMetadata = new ResourceMetadata();
+        FileResourceMetadata resourceMetadata = new FileResourceMetadata();
         FTPClient ftpClient = null;
         try {
             ftpClient = FTPTransportUtil.getFTPClient(ftpResource, ftpSecret);
@@ -98,6 +99,20 @@
     }
 
     @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
     public Boolean isAvailable(String resourceId, String credentialToken) {
 
         checkInitialized();
diff --git a/transport/gcp-transport/src/main/java/org/apache/airavata/mft/transport/gcp/GCSMetadataCollector.java b/transport/gcp-transport/src/main/java/org/apache/airavata/mft/transport/gcp/GCSMetadataCollector.java
index bda277b..aa97091 100644
--- a/transport/gcp-transport/src/main/java/org/apache/airavata/mft/transport/gcp/GCSMetadataCollector.java
+++ b/transport/gcp-transport/src/main/java/org/apache/airavata/mft/transport/gcp/GCSMetadataCollector.java
@@ -25,7 +25,8 @@
 import com.google.api.services.storage.Storage;
 import com.google.api.services.storage.StorageScopes;
 import com.google.api.services.storage.model.StorageObject;
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.credential.stubs.gcs.GCSSecret;
@@ -67,7 +68,7 @@
     }
 
     @Override
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws Exception {
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception {
         checkInitialized();
         ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
         GCSResource gcsResource = resourceClient.gcs().getGCSResource(GCSResourceGetRequest.newBuilder().setResourceId(resourceId).build());
@@ -86,7 +87,7 @@
 
         Storage storage = new Storage.Builder(transport, jsonFactory, credential).build();
 
-        ResourceMetadata metadata = new ResourceMetadata();
+        FileResourceMetadata metadata = new FileResourceMetadata();
         StorageObject gcsMetadata = storage.objects().get(gcsResource.getGcsStorage().getBucketName(),
                                                             gcsResource.getFile().getResourcePath()).execute();
         metadata.setResourceSize(gcsMetadata.getSize().longValue());
@@ -98,6 +99,20 @@
     }
 
     @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception {
         checkInitialized();
         ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
diff --git a/transport/local-transport/src/main/java/org/apache/airavata/mft/transport/local/LocalMetadataCollector.java b/transport/local-transport/src/main/java/org/apache/airavata/mft/transport/local/LocalMetadataCollector.java
index ba21a2c..f24c70f 100644
--- a/transport/local-transport/src/main/java/org/apache/airavata/mft/transport/local/LocalMetadataCollector.java
+++ b/transport/local-transport/src/main/java/org/apache/airavata/mft/transport/local/LocalMetadataCollector.java
@@ -17,7 +17,8 @@
 
 package org.apache.airavata.mft.transport.local;
 
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.resource.client.ResourceServiceClient;
@@ -56,7 +57,7 @@
     }
 
     @Override
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws Exception {
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception {
 
         ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
         LocalResource localResource = resourceClient.local().getLocalResource(LocalResourceGetRequest.newBuilder().setResourceId(resourceId).build());
@@ -64,7 +65,7 @@
         if (resourceFile.exists()) {
 
             BasicFileAttributes basicFileAttributes = Files.readAttributes(Path.of(localResource.getFile().getResourcePath()), BasicFileAttributes.class);
-            ResourceMetadata metadata = new ResourceMetadata();
+            FileResourceMetadata metadata = new FileResourceMetadata();
             metadata.setCreatedTime(basicFileAttributes.creationTime().toMillis());
             metadata.setUpdateTime(basicFileAttributes.lastModifiedTime().toMillis());
             metadata.setResourceSize(basicFileAttributes.size());
@@ -91,6 +92,20 @@
     }
 
     @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception {
        ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
         LocalResource localResource = resourceClient.local().getLocalResource(LocalResourceGetRequest.newBuilder().setResourceId(resourceId).build());
diff --git a/transport/s3-transport/src/main/java/org/apache/airavata/mft/transport/s3/S3MetadataCollector.java b/transport/s3-transport/src/main/java/org/apache/airavata/mft/transport/s3/S3MetadataCollector.java
index 5326e11..572affd 100644
--- a/transport/s3-transport/src/main/java/org/apache/airavata/mft/transport/s3/S3MetadataCollector.java
+++ b/transport/s3-transport/src/main/java/org/apache/airavata/mft/transport/s3/S3MetadataCollector.java
@@ -22,7 +22,8 @@
 import com.amazonaws.services.s3.AmazonS3;
 import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 import com.amazonaws.services.s3.model.ObjectMetadata;
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.credential.stubs.s3.S3Secret;
@@ -58,7 +59,7 @@
     }
 
     @Override
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws Exception {
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception {
 
         checkInitialized();
         ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
@@ -74,7 +75,7 @@
                 .withRegion(s3Resource.getS3Storage().getRegion())
                 .build();
 
-        ResourceMetadata metadata = new ResourceMetadata();
+        FileResourceMetadata metadata = new FileResourceMetadata();
         ObjectMetadata s3Metadata = s3Client.getObjectMetadata(s3Resource.getS3Storage().getBucketName(), s3Resource.getFile().getResourcePath());
         metadata.setResourceSize(s3Metadata.getContentLength());
         metadata.setMd5sum(s3Metadata.getETag());
@@ -84,6 +85,20 @@
     }
 
     @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception {
 
         checkInitialized();
diff --git a/transport/scp-transport/src/main/java/org/apache/airavata/mft/transport/scp/SCPMetadataCollector.java b/transport/scp-transport/src/main/java/org/apache/airavata/mft/transport/scp/SCPMetadataCollector.java
index 2c1ac22..d0086a5 100644
--- a/transport/scp-transport/src/main/java/org/apache/airavata/mft/transport/scp/SCPMetadataCollector.java
+++ b/transport/scp-transport/src/main/java/org/apache/airavata/mft/transport/scp/SCPMetadataCollector.java
@@ -20,6 +20,7 @@
 import net.schmizz.sshj.SSHClient;
 import net.schmizz.sshj.connection.channel.direct.Session;
 import net.schmizz.sshj.sftp.FileAttributes;
+import net.schmizz.sshj.sftp.RemoteResourceInfo;
 import net.schmizz.sshj.sftp.SFTPClient;
 import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
 import net.schmizz.sshj.userauth.method.AuthKeyboardInteractive;
@@ -27,13 +28,16 @@
 import net.schmizz.sshj.userauth.method.AuthPublickey;
 import net.schmizz.sshj.userauth.method.ChallengeResponseProvider;
 import net.schmizz.sshj.userauth.password.Resource;
-import org.apache.airavata.mft.core.ResourceMetadata;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
 import org.apache.airavata.mft.core.ResourceTypes;
 import org.apache.airavata.mft.core.api.MetadataCollector;
 import org.apache.airavata.mft.credential.stubs.scp.SCPSecret;
 import org.apache.airavata.mft.credential.stubs.scp.SCPSecretGetRequest;
 import org.apache.airavata.mft.resource.client.ResourceServiceClient;
 import org.apache.airavata.mft.resource.client.ResourceServiceClientBuilder;
+import org.apache.airavata.mft.resource.stubs.common.DirectoryResource;
+import org.apache.airavata.mft.resource.stubs.common.FileResource;
 import org.apache.airavata.mft.resource.stubs.scp.resource.SCPResource;
 import org.apache.airavata.mft.resource.stubs.scp.resource.SCPResourceGetRequest;
 import org.apache.airavata.mft.secret.client.SecretServiceClient;
@@ -72,15 +76,7 @@
         }
     }
 
-    public ResourceMetadata getGetResourceMetadata(String resourceId, String credentialToken) throws IOException {
-
-        checkInitialized();
-        ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
-        SCPResource scpResource = resourceClient.scp().getSCPResource(SCPResourceGetRequest.newBuilder().setResourceId(resourceId).build());
-
-        SecretServiceClient secretClient = SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
-        SCPSecret scpSecret = secretClient.scp().getSCPSecret(SCPSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
-
+    private FileResourceMetadata getFileResourceMetadata(SCPResource scpResource, SCPSecret scpSecret, String parentResourceId) throws Exception {
         try (SSHClient sshClient = getSSHClient(scpResource, scpSecret)) {
 
             logger.info("Fetching metadata for resource {} in {}", scpResource.getFile().getResourcePath(), scpResource.getScpStorage().getHost());
@@ -89,10 +85,14 @@
                 FileAttributes lstat = sftpClient.lstat(scpResource.getFile().getResourcePath());
                 sftpClient.close();
 
-                ResourceMetadata metadata = new ResourceMetadata();
+                FileResourceMetadata metadata = new FileResourceMetadata();
                 metadata.setResourceSize(lstat.getSize());
                 metadata.setCreatedTime(lstat.getAtime());
                 metadata.setUpdateTime(lstat.getMtime());
+                metadata.setParentResourceId(parentResourceId);
+                metadata.setParentResourceType("SCP");
+                metadata.setFriendlyName(new File(scpResource.getFile().getResourcePath()).getName());
+                metadata.setResourcePath(scpResource.getFile().getResourcePath());
 
                 try {
                     // TODO calculate md5 using the binary based on the OS platform. Eg: MacOS has md5. Linux has md5sum
@@ -111,14 +111,121 @@
                         logger.warn("MD5 fetch error out {}", errorWriter.toString());
                     }
                 } catch (Exception e) {
-                    logger.warn("Failed to fetch md5 for SCP resource {}", resourceId, e);
+                    logger.warn("Failed to fetch md5 for SCP resource {}", scpResource.getResourceId(), e);
                 }
-
                 return metadata;
             }
         }
     }
 
+    public FileResourceMetadata getFileResourceMetadata(String resourceId, String credentialToken) throws Exception {
+
+        checkInitialized();
+        ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
+        SCPResource scpResource = resourceClient.scp().getSCPResource(SCPResourceGetRequest.newBuilder().setResourceId(resourceId).build());
+
+        SecretServiceClient secretClient = SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
+        SCPSecret scpSecret = secretClient.scp().getSCPSecret(SCPSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
+
+        return getFileResourceMetadata(scpResource, scpSecret, resourceId);
+    }
+
+    @Override
+    public FileResourceMetadata getFileResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
+        SCPResource parentSCPResource = resourceClient.scp().getSCPResource(SCPResourceGetRequest.newBuilder().setResourceId(parentResourceId).build());
+
+        SecretServiceClient secretClient = SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
+        SCPSecret scpSecret = secretClient.scp().getSCPSecret(SCPSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
+
+        validateParent(parentSCPResource, resourcePath);
+
+        SCPResource scpResource = SCPResource.newBuilder()
+                                        .setFile(FileResource.newBuilder()
+                                        .setResourcePath(resourcePath).build())
+                                        .setScpStorage(parentSCPResource.getScpStorage()).build();
+
+        return getFileResourceMetadata(scpResource, scpSecret, parentResourceId);
+    }
+
+    private DirectoryResourceMetadata getDirectoryResourceMetadata(SCPResource scpResource, SCPSecret scpSecret, String parentResourceId) throws Exception {
+        try (SSHClient sshClient = getSSHClient(scpResource, scpSecret)) {
+
+            logger.info("Fetching metadata for resource {} in {}", scpResource.getFile().getResourcePath(), scpResource.getScpStorage().getHost());
+
+            try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
+                List<RemoteResourceInfo> lsOut = sftpClient.ls(scpResource.getDirectory().getResourcePath());
+                FileAttributes lsStat = sftpClient.lstat(scpResource.getDirectory().getResourcePath());
+                sftpClient.close();
+
+                DirectoryResourceMetadata.Builder dirMetadataBuilder = DirectoryResourceMetadata.Builder.getBuilder()
+                                        .withLazyInitialized(false);
+
+                for (RemoteResourceInfo rri : lsOut) {
+                    if (rri.isDirectory()) {
+                        DirectoryResourceMetadata.Builder childDirBuilder = DirectoryResourceMetadata.Builder.getBuilder()
+                                        .withFriendlyName(rri.getName())
+                                        .withResourcePath(rri.getPath())
+                                        .withCreatedTime(rri.getAttributes().getAtime())
+                                        .withUpdateTime(rri.getAttributes().getMtime())
+                                        .withParentResourceId(parentResourceId)
+                                        .withParentResourceType("SCP");
+                        dirMetadataBuilder = dirMetadataBuilder.withDirectory(childDirBuilder.build());
+                    }
+
+                    if (rri.isRegularFile()) {
+                        FileResourceMetadata.Builder childFileBuilder = FileResourceMetadata.Builder.getBuilder()
+                                        .withFriendlyName(rri.getName())
+                                        .withResourcePath(rri.getPath())
+                                        .withCreatedTime(rri.getAttributes().getAtime())
+                                        .withUpdateTime(rri.getAttributes().getMtime())
+                                        .withParentResourceId(parentResourceId)
+                                        .withParentResourceType("SCP");
+
+                        dirMetadataBuilder = dirMetadataBuilder.withFile(childFileBuilder.build());
+                    }
+                }
+
+                dirMetadataBuilder = dirMetadataBuilder.withFriendlyName(new File(scpResource.getDirectory().getResourcePath()).getName())
+                        .withResourcePath(parentResourceId)
+                        .withCreatedTime(lsStat.getAtime())
+                        .withUpdateTime(lsStat.getMtime())
+                        .withParentResourceId(parentResourceId)
+                        .withParentResourceType("SCP");
+                return dirMetadataBuilder.build();
+            }
+        }
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String resourceId, String credentialToken) throws Exception {
+
+        ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
+        SCPResource scpPResource = resourceClient.scp().getSCPResource(SCPResourceGetRequest.newBuilder().setResourceId(resourceId).build());
+
+        SecretServiceClient secretClient = SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
+        SCPSecret scpSecret = secretClient.scp().getSCPSecret(SCPSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
+
+        return getDirectoryResourceMetadata(scpPResource, scpSecret, resourceId);
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(String parentResourceId, String resourcePath, String credentialToken) throws Exception {
+        ResourceServiceClient resourceClient = ResourceServiceClientBuilder.buildClient(resourceServiceHost, resourceServicePort);
+        SCPResource parentSCPPResource = resourceClient.scp().getSCPResource(SCPResourceGetRequest.newBuilder().setResourceId(parentResourceId).build());
+
+        SecretServiceClient secretClient = SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
+        SCPSecret scpSecret = secretClient.scp().getSCPSecret(SCPSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
+
+        validateParent(parentSCPPResource, resourcePath);
+
+        SCPResource scpResource = SCPResource.newBuilder().setScpStorage(parentSCPPResource.getScpStorage())
+                        .setDirectory(DirectoryResource.newBuilder()
+                        .setResourcePath(resourcePath).build()).build();
+
+        return getDirectoryResourceMetadata(scpResource, scpSecret, parentResourceId);
+    }
+
     @Override
     public Boolean isAvailable(String resourceId, String credentialToken) throws Exception {
 
@@ -143,6 +250,22 @@
         }
     }
 
+    private void validateParent(SCPResource parentSCPResource, String resourcePath) throws Exception {
+        if (!ResourceTypes.DIRECTORY.equals(parentSCPResource.getResourceCase().name())) {
+            logger.error("Parent resource " + parentSCPResource.getResourceId() + " is not a DIRECTORY type");
+            throw new Exception("Parent resource " + parentSCPResource.getResourceId() + " is not a DIRECTORY type");
+        }
+
+        String parentDir = parentSCPResource.getDirectory().getResourcePath();
+        parentDir = parentDir.endsWith(File.separator) ? parentDir : parentDir + File.separator;
+        if (!resourcePath.startsWith(parentDir)) {
+            logger.error("Given resource path " + resourcePath + " is not a part of the parent resource path "
+                    + parentSCPResource.getDirectory().getResourcePath());
+            throw new Exception("Given resource path " + resourcePath + " is not a part of the parent resource path "
+                    + parentSCPResource.getDirectory().getResourcePath());
+        }
+    }
+
     private SSHClient getSSHClient(SCPResource scpResource, SCPSecret scpSecret) throws IOException {
 
         SSHClient sshClient = new SSHClient();