diff --git a/libs/middletier/SqliteDatabase.cpp b/libs/middletier/SqliteDatabase.cpp
index 9786ee106c8a77f8deed47230b901c4382a8dfd1..d47ead86a1d19199876172d968da3b040a1b2e0e 100644
--- a/libs/middletier/SqliteDatabase.cpp
+++ b/libs/middletier/SqliteDatabase.cpp
@@ -113,64 +113,6 @@ void cta::SqliteDatabase::createTapePoolTable() {
   }
 }
 
-//------------------------------------------------------------------------------
-// createDirectoryTable
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::createDirectoryTable() {
-  char *zErrMsg = 0;
-  int rc = sqlite3_exec(m_dbHandle, 
-          "CREATE TABLE DIRECTORY("
-            "PATH              TEXT     PRIMARY KEY,"
-            "STORAGECLASS_NAME TEXT,"
-            "UID               INTEGER,"
-            "GID               INTEGER,"
-            "CREATIONTIME      INTEGER,"
-            "MODE              INTEGER,"
-            "FOREIGN KEY (STORAGECLASS_NAME) REFERENCES STORAGECLASS(NAME)"
-            ");",
-          0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "createDirectoryTable() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-  std::ostringstream query;
-  query << "INSERT INTO DIRECTORY VALUES('/',NULL,0,0," << (int)time(NULL) << ",0);";
-  rc = sqlite3_exec(m_dbHandle, query.str().c_str(), 0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "createDirectoryTable() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-}
-
-//------------------------------------------------------------------------------
-// createFileTable
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::createFileTable() {
-  char *zErrMsg = 0;
-  int rc = sqlite3_exec(m_dbHandle, 
-          "CREATE TABLE FILE("
-            "PATH           TEXT,"
-            "NAME           TEXT,"
-            "UID            INTEGER,"
-            "GID            INTEGER,"
-            "CREATIONTIME   INTEGER,"
-            "MODE           INTEGER,"
-            "PRIMARY KEY (PATH, NAME),"
-            "FOREIGN KEY (PATH) REFERENCES DIRECTORY(PATH)"
-            ");",
-          0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "createFileTable() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-}
-
 //------------------------------------------------------------------------------
 // createTapeTable
 //------------------------------------------------------------------------------
@@ -329,8 +271,6 @@ void cta::SqliteDatabase::createSchema() {
   createStorageClassTable();
   createTapePoolTable();
   createArchiveRouteTable();
-  createDirectoryTable();
-  createFileTable();
   createLogicalLibraryTable();
   createTapeTable();
   createAdminUserTable();  
@@ -435,283 +375,6 @@ void cta::SqliteDatabase::insertLogicalLibrary(const SecurityIdentity &requester
   }
 }
   
-//------------------------------------------------------------------------------
-// insertFile
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::insertFile(const SecurityIdentity &requester, const std::string &pathname, const uint16_t mode) {
-  cta::Utils::checkAbsolutePathSyntax(pathname);
-  std::string path = cta::Utils::getEnclosingDirPath(pathname);
-  std::string name = cta::Utils::getEnclosedName(pathname);
-  getDirectoryStorageClass(requester, path); //just check if the path exists
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "INSERT INTO FILE VALUES('" << path << "','" << name << "',"<< requester.user.getUid() << "," << requester.user.getGid() << "," << (int)time(NULL) << "," << (int)mode << ");";
-  int rc = sqlite3_exec(m_dbHandle, query.str().c_str(), 0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "insertFile() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-}
-
-//------------------------------------------------------------------------------
-// checkFileExists
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::checkFileExists(const std::string &path, const std::string &name){
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "SELECT * FROM FILE WHERE NAME='" << name << "' AND PATH='" << path << "';";
-  sqlite3_stmt *statement;
-  int rc = sqlite3_prepare(m_dbHandle, query.str().c_str(), -1, &statement, 0 );
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "checkFileExists() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-  int res = sqlite3_step(statement);
-  if(res==SQLITE_ROW) {
-    return;
-  } 
-  else if(res==SQLITE_DONE){
-    std::ostringstream message;
-    message << "FILE: " << path << "/" << name << " does not exist";
-    throw(Exception(message.str()));    
-  }
-  else {
-    std::ostringstream message;
-    message << "checkFileExists() - SQLite error: " << zErrMsg;
-    sqlite3_free(zErrMsg);
-    throw(Exception(message.str()));    
-  }  
-}
-
-//------------------------------------------------------------------------------
-// deleteFile
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::deleteFile(const SecurityIdentity &requester, const std::string &pathname) {
-  cta::Utils::checkAbsolutePathSyntax(pathname);
-  std::string path = cta::Utils::getEnclosingDirPath(pathname);
-  std::string name = cta::Utils::getEnclosedName(pathname);
-  checkFileExists(path, name);
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "DELETE FROM FILE WHERE NAME='" << name << "' AND PATH='" << path << "';";
-  int rc = sqlite3_exec(m_dbHandle, query.str().c_str(), 0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "deleteFile() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-}
-
-//------------------------------------------------------------------------------
-// getDirectoryStorageClass
-//------------------------------------------------------------------------------
-std::string cta::SqliteDatabase::getDirectoryStorageClass(const SecurityIdentity &requester, const std::string &path){
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  std::list<cta::TapePool> pools;
-  query << "SELECT STORAGECLASS_NAME FROM DIRECTORY WHERE PATH='" << path << "';";
-  sqlite3_stmt *statement;
-  int rc = sqlite3_prepare(m_dbHandle, query.str().c_str(), -1, &statement, 0 );
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "getDirectoryStorageClass() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-  int res = sqlite3_step(statement);
-  if(res==SQLITE_ROW) {
-    return std::string((char *)sqlite3_column_text(statement,0));
-  }
-  else if(res==SQLITE_DONE){
-    std::ostringstream message;
-    message << "PATH: " << path << " does not exist";
-    throw(Exception(message.str()));    
-  }
-  else {
-    std::ostringstream message;
-    message << "getDirectoryStorageClass() - SQLite error: " << zErrMsg;
-    sqlite3_free(zErrMsg);
-    throw(Exception(message.str()));    
-  }
-}
-
-//------------------------------------------------------------------------------
-// setDirectoryStorageClass
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::setDirectoryStorageClass(const SecurityIdentity &requester, const std::string &path, const std::string &storageClassName){
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "UPDATE DIRECTORY SET STORAGECLASS_NAME='" << storageClassName << "' WHERE PATH='" << path << "';";
-  int rc = sqlite3_exec(m_dbHandle, query.str().c_str(), 0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "setDirectoryStorageClass() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-}
-
-//------------------------------------------------------------------------------
-// clearDirectoryStorageClass
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::clearDirectoryStorageClass(const SecurityIdentity &requester, const std::string &path){
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "UPDATE DIRECTORY SET STORAGECLASS_NAME=NULL WHERE PATH='" << path << "';";
-  int rc = sqlite3_exec(m_dbHandle, query.str().c_str(), 0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "clearDirectoryStorageClass() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-}
-
-//------------------------------------------------------------------------------
-// checkDirectoryExists
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::checkDirectoryExists(const std::string &path){
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "SELECT * FROM DIRECTORY WHERE PATH='" << path << "';";
-  sqlite3_stmt *statement;
-  int rc = sqlite3_prepare(m_dbHandle, query.str().c_str(), -1, &statement, 0 );
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "checkDirectoryExists() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-  int res = sqlite3_step(statement);
-  if(res==SQLITE_ROW) {
-    return;
-  } 
-  else if(res==SQLITE_DONE){
-    std::ostringstream message;
-    message << "DIRECTORY: " << path << " does not exist";
-    throw(Exception(message.str()));    
-  }
-  else {
-    std::ostringstream message;
-    message << "checkDirectoryExists() - SQLite error: " << zErrMsg;
-    sqlite3_free(zErrMsg);
-    throw(Exception(message.str()));    
-  }  
-}
-
-//------------------------------------------------------------------------------
-// checkDirectoryContainsNoDirectories
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::checkDirectoryContainsNoDirectories(const std::string &path){
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "SELECT * FROM DIRECTORY WHERE PATH LIKE '" << path << "%';";
-  sqlite3_stmt *statement;
-  int rc = sqlite3_prepare(m_dbHandle, query.str().c_str(), -1, &statement, 0 );
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "checkDirectoryContainsNoDirectories() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-  sqlite3_step(statement); // we will have at least one match: the directory itself. so we skip the first result!
-  int res = sqlite3_step(statement);
-  if(res==SQLITE_ROW) {
-    std::ostringstream message;
-    message << "DIRECTORY " << path << " not empty: contains at least one directory";
-    throw(Exception(message.str()));
-  } 
-  else if(res==SQLITE_DONE){ //OK
-  }
-  else {
-    std::ostringstream message;
-    message << "checkDirectoryContainsNoDirectories() - SQLite error: " << zErrMsg;
-    sqlite3_free(zErrMsg);
-    throw(Exception(message.str()));    
-  }
-}
-
-//------------------------------------------------------------------------------
-// checkDirectoryContainsNoFiles
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::checkDirectoryContainsNoFiles(const std::string &path){
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "SELECT * FROM FILE WHERE PATH='" << path << "%';";
-  sqlite3_stmt *statement;
-  int rc = sqlite3_prepare(m_dbHandle, query.str().c_str(), -1, &statement, 0 );
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "checkDirectoryContainsNoFiles() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-  int res = sqlite3_step(statement);
-  if(res==SQLITE_ROW) {
-    std::ostringstream message;
-    message << "DIRECTORY " << path << " not empty: contains at least one file";
-    throw(Exception(message.str()));
-  } 
-  else if(res==SQLITE_DONE){ //OK
-  }
-  else {
-    std::ostringstream message;
-    message << "checkDirectoryContainsNoFiles() - SQLite error: " << zErrMsg;
-    sqlite3_free(zErrMsg);
-    throw(Exception(message.str()));    
-  }
-}
-
-//------------------------------------------------------------------------------
-// deleteDirectory
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::deleteDirectory(const SecurityIdentity &requester, const std::string &pathname) {
-  cta::Utils::checkAbsolutePathSyntax(pathname);
-  checkDirectoryExists(pathname);
-  checkDirectoryContainsNoDirectories(pathname);
-  checkDirectoryContainsNoFiles(pathname);
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  query << "DELETE FROM DIRECTORY WHERE PATH='" << pathname << "';";
-  int rc = sqlite3_exec(m_dbHandle, query.str().c_str(), 0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-      std::ostringstream message;
-      message << "deleteDirectory() - SQLite error: " << zErrMsg;
-      sqlite3_free(zErrMsg);
-      throw(Exception(message.str()));
-  }
-}
-
-//------------------------------------------------------------------------------
-// insertDirectory
-//------------------------------------------------------------------------------
-void cta::SqliteDatabase::insertDirectory(const SecurityIdentity &requester, const std::string &pathname, const uint16_t mode) {
-  cta::Utils::checkAbsolutePathSyntax(pathname);
-  std::string path = cta::Utils::getEnclosingDirPath(pathname);
-  std::string name = cta::Utils::getEnclosedName(pathname);
-  std::string storageClass = getDirectoryStorageClass(requester, path);
-  char *zErrMsg = 0;
-  std::ostringstream query;
-  if(storageClass!="") {
-    query << "INSERT INTO DIRECTORY VALUES('" << pathname << "','" << storageClass << "'," << requester.user.getUid() << "," << requester.user.getGid() << "," << (int)time(NULL) << "," << (int)mode << ");";
-  }
-  else {
-    query << "INSERT INTO DIRECTORY VALUES('" << pathname << "',NULL," << requester.user.getUid() << "," << requester.user.getGid() << "," << (int)mode << ");";
-  }
-  int rc = sqlite3_exec(m_dbHandle, query.str().c_str(), 0, 0, &zErrMsg);
-  if(rc!=SQLITE_OK){    
-    std::ostringstream message;
-    message << "insertDirectory() - SQLite error: " << zErrMsg;
-    sqlite3_free(zErrMsg);
-    throw(Exception(message.str()));
-  }
-}
-
 //------------------------------------------------------------------------------
 // insertTapePool
 //------------------------------------------------------------------------------
diff --git a/libs/middletier/SqliteDatabase.hpp b/libs/middletier/SqliteDatabase.hpp
index 13117b811eefe359526539e63096a3c21b1d2adf..830e2f0dc4840a3de95f1f9e750d11630239435f 100644
--- a/libs/middletier/SqliteDatabase.hpp
+++ b/libs/middletier/SqliteDatabase.hpp
@@ -93,28 +93,7 @@ public:
   
   cta::TapePool getTapePoolByName(const SecurityIdentity &requester, const std::string &name);
   
-  cta::Tape getTapeByVid(const SecurityIdentity &requester, const std::string &vid);
-  
-  
-  
-  
-  void setDirectoryStorageClass(const SecurityIdentity &requester, const std::string &path, const std::string &storageClassName);
-  
-  void clearDirectoryStorageClass(const SecurityIdentity &requester, const std::string &path);
-  
-  std::string getDirectoryStorageClass(const SecurityIdentity &requester, const std::string &path);
-  
-  void insertFile(const SecurityIdentity &requester, const std::string &pathname, const uint16_t mode);
-  
-  void insertDirectory(const SecurityIdentity &requester, const std::string &pathname, const uint16_t mode);
-  
-  void deleteFile(const SecurityIdentity &requester, const std::string &pathname);
-  
-  void deleteDirectory(const SecurityIdentity &requester, const std::string &pathname);    
-  
-//  cta::DirectoryIterator getDirectoryContents(const SecurityIdentity &requester, const std::string &dirPath);
-  
-  
+  cta::Tape getTapeByVid(const SecurityIdentity &requester, const std::string &vid);  
 
 private:
   
@@ -161,21 +140,6 @@ private:
   
   void checkLogicalLibraryExists(const std::string &name);
   
-  
-  
-  
-  void checkFileExists(const std::string &path, const std::string &name);
-  
-  void checkDirectoryExists(const std::string &path);
-  
-  void checkDirectoryContainsNoDirectories(const std::string &path);
-  
-  void checkDirectoryContainsNoFiles(const std::string &path);
-  
-  void createDirectoryTable();
-  
-  void createFileTable();
-  
 }; // struct SqliteDatabase
 
 } // namespace cta
diff --git a/libs/middletier/SqliteMiddleTierAdmin.cpp b/libs/middletier/SqliteMiddleTierAdmin.cpp
index 0e285a9c855a805529bba4db0acce8fdbf62522a..6077ab2135f8fa69240683c43f0ae7360f8620e9 100644
--- a/libs/middletier/SqliteMiddleTierAdmin.cpp
+++ b/libs/middletier/SqliteMiddleTierAdmin.cpp
@@ -8,8 +8,8 @@
 //------------------------------------------------------------------------------
 // constructor
 //------------------------------------------------------------------------------
-cta::SqliteMiddleTierAdmin::SqliteMiddleTierAdmin(SqliteDatabase &sqlite_db):
-  m_sqlite_db(sqlite_db) {
+cta::SqliteMiddleTierAdmin::SqliteMiddleTierAdmin(Vfs &vfs, SqliteDatabase &sqlite_db):
+  m_sqlite_db(sqlite_db), m_vfs(vfs) {
 }
 
 //------------------------------------------------------------------------------
@@ -86,6 +86,7 @@ void cta::SqliteMiddleTierAdmin::createStorageClass(
 //------------------------------------------------------------------------------
 void cta::SqliteMiddleTierAdmin::deleteStorageClass(const SecurityIdentity &requester,
   const std::string &name) {
+  m_vfs.checkStorageClassIsNotInUse(requester, name, "/");
   m_sqlite_db.deleteStorageClass(requester, name);
 }
 
diff --git a/libs/middletier/SqliteMiddleTierAdmin.hpp b/libs/middletier/SqliteMiddleTierAdmin.hpp
index e503a2eb1c6c5fff397b958fd5b0cdb4eac79cd4..9d7a4b5446b5450a984b58a84bbdb3c77117956b 100644
--- a/libs/middletier/SqliteMiddleTierAdmin.hpp
+++ b/libs/middletier/SqliteMiddleTierAdmin.hpp
@@ -3,6 +3,7 @@
 #include "MiddleTierAdmin.hpp"
 #include "MockDatabase.hpp"
 #include "SqliteDatabase.hpp"
+#include "Vfs.hpp"
 
 namespace cta {
 
@@ -17,7 +18,7 @@ public:
    *
    * @param db The database of the mock middle-tier.
    */
-  SqliteMiddleTierAdmin(SqliteDatabase &sqlite_db);
+  SqliteMiddleTierAdmin(Vfs &vfs, SqliteDatabase &sqlite_db);
 
   /**
    * Destructor.
@@ -315,6 +316,8 @@ protected:
   bool isAnExistingDirectory(const std::string &path) const throw();
   
   SqliteDatabase &m_sqlite_db;
+  
+  Vfs &m_vfs;
 
 }; // class SqliteMiddleTierAdmin
 
diff --git a/libs/middletier/SqliteMiddleTierAdminTest.cpp b/libs/middletier/SqliteMiddleTierAdminTest.cpp
index 91d58ca3ebdc9cc4662b84c2c57eeff6c964ad13..060055d8b28417eb226243e5a93af5045aa1e9f2 100644
--- a/libs/middletier/SqliteMiddleTierAdminTest.cpp
+++ b/libs/middletier/SqliteMiddleTierAdminTest.cpp
@@ -21,7 +21,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, createStorageClass_new) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -53,7 +54,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest,
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -87,7 +89,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest,
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -120,7 +123,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, deleteStorageClass_existing) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -159,7 +163,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest,
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -185,7 +190,6 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest,
     ASSERT_EQ(nbCopies, storageClass.getNbCopies());
   }
 
-  Vfs vfs;
   SqliteMiddleTierUser userApi(vfs,sqlitedb);
   ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, "/",
     storageClassName));
@@ -219,7 +223,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, deleteStorageClass_in_use_by_route)
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -313,7 +318,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, deleteStorageClass_non_existing) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -336,7 +342,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, deleteTapePool_in_use) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -394,7 +401,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, createArchiveRoute_new) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -439,7 +447,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest,
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -486,7 +495,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, deleteArchiveRoute_existing) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -539,7 +549,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, deleteArchiveRoute_non_existing) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -571,7 +582,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, createTape_new) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -650,7 +662,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest,
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
@@ -701,7 +714,8 @@ TEST_F(cta_client_SqliteMiddleTierAdminTest, createTape_new_non_existing_pool) {
   using namespace cta;
 
   SqliteDatabase sqlitedb;
-  SqliteMiddleTierAdmin adminApi(sqlitedb);
+  Vfs vfs;
+  SqliteMiddleTierAdmin adminApi(vfs, sqlitedb);
   const SecurityIdentity requester;
 
   {
diff --git a/libs/middletier/SqliteMiddleTierUser.cpp b/libs/middletier/SqliteMiddleTierUser.cpp
index 1d98f79e0fb84e2c7d045b87878dd3891b67d967..4920592c89a9fe9737949dd5cc39d5efc3169ad7 100644
--- a/libs/middletier/SqliteMiddleTierUser.cpp
+++ b/libs/middletier/SqliteMiddleTierUser.cpp
@@ -24,7 +24,7 @@ cta::SqliteMiddleTierUser::~SqliteMiddleTierUser() throw() {
 //------------------------------------------------------------------------------
 void cta::SqliteMiddleTierUser::createDirectory(const SecurityIdentity &requester,
   const std::string &dirPath) {
-  m_vfs.clearDirectoryStorageClass(requester, dirPath);
+  m_vfs.createDirectory(requester, dirPath, 0777);
 }
 
 //------------------------------------------------------------------------------
diff --git a/libs/middletier/SqliteMiddleTierUserTest.cpp b/libs/middletier/SqliteMiddleTierUserTest.cpp
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3ab30df7b81327c0414fd403a90b8fc75eaca082 100644
--- a/libs/middletier/SqliteMiddleTierUserTest.cpp
+++ b/libs/middletier/SqliteMiddleTierUserTest.cpp
@@ -0,0 +1,976 @@
+#include "SqliteMiddleTierAdmin.hpp"
+#include "SqliteMiddleTierUser.hpp"
+
+#include <gtest/gtest.h>
+#include <set>
+
+namespace unitTests {
+
+class cta_client_SqliteMiddleTierUserTest: public ::testing::Test {
+protected:
+
+  virtual void SetUp() {
+  }
+
+  virtual void TearDown() {
+  }
+};
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  getDirectoryContents_root_dir_is_empty) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "/";
+
+  DirectoryIterator itor;
+  ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+  ASSERT_FALSE(itor.hasMore());
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, createDirectory_empty_string) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "";
+
+  ASSERT_THROW(userApi.createDirectory(requester, dirPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  createDirectory_consecutive_slashes) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "//";
+
+  ASSERT_THROW(userApi.createDirectory(requester, dirPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, createDirectory_invalid_chars) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "/grandparent/?parent";
+  
+  ASSERT_THROW(userApi.createDirectory(requester, dirPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, createDirectory_top_level) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "/grandparent";
+  
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+
+  DirectoryIterator itor;
+
+  ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+  ASSERT_TRUE(itor.hasMore());
+
+  DirectoryEntry entry;
+
+  ASSERT_NO_THROW(entry = itor.next());
+
+  ASSERT_EQ(std::string("grandparent"), entry.getName());
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, createDirectory_second_level) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+
+  ASSERT_TRUE(userApi.getDirectoryStorageClass(requester, "/").empty());
+
+  {
+    const std::string topLevelDirPath = "/grandparent";
+
+    ASSERT_NO_THROW(userApi.createDirectory(requester, topLevelDirPath));
+  }
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+  }
+
+  ASSERT_TRUE(userApi.getDirectoryStorageClass(requester, "/grandparent").empty());
+
+  {
+    const std::string secondLevelDirPath = "/grandparent/parent";
+
+    ASSERT_NO_THROW(userApi.createDirectory(requester, secondLevelDirPath));
+  }
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+  }
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/grandparent"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("parent"), entry.getName());
+  }
+
+  ASSERT_TRUE(userApi.getDirectoryStorageClass(requester,
+    "/grandparent/parent").empty());
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  createDirectory_inherit_storage_class) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+
+  ASSERT_TRUE(userApi.getDirectoryStorageClass(requester, "/").empty());
+
+  {
+    SqliteMiddleTierAdmin adminApi(vfs, db);
+    const std::string name = "TestStorageClass";
+    const uint16_t nbCopies = 2;
+    const std::string comment = "Comment";
+    ASSERT_NO_THROW(adminApi.createStorageClass(requester, name, nbCopies, comment));
+  }
+
+  {
+    const std::string topLevelDirPath = "/grandparent";
+
+    ASSERT_NO_THROW(userApi.createDirectory(requester, topLevelDirPath));
+  }
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+
+    ASSERT_TRUE(userApi.getDirectoryStorageClass(requester, "/grandparent").empty());
+
+    ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, "/grandparent",
+      "TestStorageClass"));
+  }
+
+  ASSERT_EQ(std::string("TestStorageClass"),
+    userApi.getDirectoryStorageClass(requester, "/grandparent"));
+
+  {
+    const std::string secondLevelDirPath = "/grandparent/parent";
+
+    ASSERT_NO_THROW(userApi.createDirectory(requester, secondLevelDirPath));
+  }
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+  }
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/grandparent"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("parent"), entry.getName());
+  }
+
+  ASSERT_EQ(std::string("TestStorageClass"),
+    userApi.getDirectoryStorageClass(requester, "/grandparent/parent"));
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, deleteDirectory_root) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "/";
+
+  ASSERT_THROW(userApi.deleteDirectory(requester, "/"), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, deleteDirectory_existing_top_level) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "/grandparent";
+  
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+  }
+
+  ASSERT_NO_THROW(userApi.deleteDirectory(requester, "/grandparent"));
+
+  {
+    DirectoryIterator itor;
+  
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+  
+    ASSERT_FALSE(itor.hasMore());
+  }
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  deleteDirectory_non_empty_top_level) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+
+  {
+    const std::string topLevelDirPath = "/grandparent";
+
+    ASSERT_NO_THROW(userApi.createDirectory(requester, topLevelDirPath));
+
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+  }
+
+  {
+    const std::string secondLevelDirPath = "/grandparent/parent";
+
+    ASSERT_NO_THROW(userApi.createDirectory(requester, secondLevelDirPath));
+
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+  }
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/grandparent"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("parent"), entry.getName());
+  }
+
+  ASSERT_THROW(userApi.deleteDirectory(requester, "/grandparent"), std::exception);
+
+  {
+    DirectoryIterator itor;
+
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/grandparent"));
+
+    ASSERT_TRUE(itor.hasMore());
+
+    DirectoryEntry entry;
+
+    ASSERT_NO_THROW(entry = itor.next());
+
+    ASSERT_EQ(std::string("parent"), entry.getName());
+  }
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  deleteDirectory_non_existing_top_level) {
+  using namespace cta;
+  
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+
+  ASSERT_THROW(userApi.deleteDirectory(requester, "/grandparent"), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, setDirectoryStorageClass_top_level) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "/grandparent";
+
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+
+  DirectoryIterator itor;
+
+  ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+  ASSERT_TRUE(itor.hasMore());
+
+  DirectoryEntry entry;
+
+  ASSERT_NO_THROW(entry = itor.next());
+
+  ASSERT_EQ(std::string("grandparent"), entry.getName());
+
+  {
+    std::string name;
+    ASSERT_NO_THROW(name = userApi.getDirectoryStorageClass(requester, dirPath));
+    ASSERT_TRUE(name.empty());
+  }
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 2;
+    const std::string comment = "Comment";
+  {
+    SqliteMiddleTierAdmin adminApi(vfs, db);
+    ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+      nbCopies, comment));
+  }
+
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  {
+    std::string name;
+    ASSERT_NO_THROW(name = userApi.getDirectoryStorageClass(requester, dirPath));
+    ASSERT_EQ(storageClassName, name);
+  }
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  clearDirectoryStorageClass_top_level) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  const SecurityIdentity requester;
+  const std::string dirPath = "/grandparent";
+
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+
+  DirectoryIterator itor;
+
+  ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+
+  ASSERT_TRUE(itor.hasMore());
+
+  DirectoryEntry entry;
+
+  ASSERT_NO_THROW(entry = itor.next());
+
+  ASSERT_EQ(std::string("grandparent"), entry.getName());
+
+  {
+    std::string name;
+    ASSERT_NO_THROW(name = userApi.getDirectoryStorageClass(requester, dirPath));
+    ASSERT_TRUE(name.empty());
+  }
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 2;
+  const std::string comment = "Comment";
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, comment));
+
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  {
+    std::string name;
+    ASSERT_NO_THROW(name = userApi.getDirectoryStorageClass(requester, dirPath));
+    ASSERT_EQ(storageClassName, name);
+  }
+
+  ASSERT_THROW(adminApi.deleteStorageClass(requester, storageClassName),
+    std::exception);
+
+  ASSERT_NO_THROW(userApi.clearDirectoryStorageClass(requester, dirPath));
+
+  {
+    std::string name;
+    ASSERT_NO_THROW(name = userApi.getDirectoryStorageClass(requester, dirPath));
+    ASSERT_TRUE(name.empty());
+  }
+
+  ASSERT_NO_THROW(adminApi.deleteStorageClass(requester, storageClassName));
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, archive_to_new_file) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 1;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  const std::string tapePoolName = "TestTapePool";
+  const uint16_t nbDrives = 1;
+  const uint16_t nbPartialTapes = 1;
+  const std::string tapePoolComment = "Tape-pool comment";
+  ASSERT_NO_THROW(adminApi.createTapePool(requester, tapePoolName, nbDrives,
+    nbPartialTapes, tapePoolComment));
+
+  const uint16_t copyNb = 1;
+  const std::string archiveRouteComment = "Archive-route comment";
+  ASSERT_NO_THROW(adminApi.createArchiveRoute(requester, storageClassName,
+    copyNb, tapePoolName, archiveRouteComment));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl");
+  const std::string dstPath  = "/grandparent/parent_file";
+  ASSERT_NO_THROW(userApi.archive(requester, srcUrls, dstPath));
+
+  {
+    DirectoryIterator itor;
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+    ASSERT_TRUE(itor.hasMore());
+    DirectoryEntry entry;
+    ASSERT_NO_THROW(entry = itor.next());
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+    ASSERT_EQ(DirectoryEntry::ENTRYTYPE_DIRECTORY, entry.getType());
+    ASSERT_EQ(storageClassName, entry.getStorageClassName());
+  }
+
+  {
+    DirectoryIterator itor;
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester,
+      "/grandparent"));
+    ASSERT_TRUE(itor.hasMore());
+    DirectoryEntry entry;
+    ASSERT_NO_THROW(entry = itor.next());
+    ASSERT_EQ(std::string("parent_file"), entry.getName());
+    ASSERT_EQ(DirectoryEntry::ENTRYTYPE_FILE, entry.getType());
+    ASSERT_EQ(storageClassName, entry.getStorageClassName());
+  }
+
+  {
+    DirectoryEntry entry;
+    ASSERT_NO_THROW(entry = userApi.stat(requester, dstPath));
+    ASSERT_EQ(DirectoryEntry::ENTRYTYPE_FILE, entry.getType());
+    ASSERT_EQ(storageClassName, entry.getStorageClassName());
+  }
+
+  {
+    const std::map<TapePool, std::list<ArchivalJob> > allJobs =
+      userApi.getArchivalJobs(requester);
+    ASSERT_EQ(1, allJobs.size());
+    std::map<TapePool, std::list<ArchivalJob> >::const_iterator
+      poolItor = allJobs.begin();
+    ASSERT_FALSE(poolItor == allJobs.end());
+    const TapePool &pool = poolItor->first;
+    ASSERT_TRUE(tapePoolName == pool.getName());
+    const std::list<ArchivalJob> &poolJobs = poolItor->second;
+    ASSERT_EQ(1, poolJobs.size());
+    std::set<std::string> srcUrls;
+    std::set<std::string> dstPaths;
+    for(std::list<ArchivalJob>::const_iterator jobItor = poolJobs.begin();
+      jobItor != poolJobs.end(); jobItor++) {
+      ASSERT_EQ(ArchivalJobState::PENDING, jobItor->getState());
+      srcUrls.insert(jobItor->getSrcUrl());
+      dstPaths.insert(jobItor->getDstPath());
+    }
+    ASSERT_EQ(1, srcUrls.size());
+    ASSERT_FALSE(srcUrls.find("diskUrl") == srcUrls.end());
+    ASSERT_EQ(1, dstPaths.size());
+    ASSERT_FALSE(dstPaths.find("/grandparent/parent_file") == dstPaths.end());
+  }
+
+  {
+    const std::list<ArchivalJob> poolJobs = userApi.getArchivalJobs(requester,
+      tapePoolName);
+    ASSERT_EQ(1, poolJobs.size());
+    std::set<std::string> srcUrls;
+    std::set<std::string> dstPaths;
+    for(std::list<ArchivalJob>::const_iterator jobItor = poolJobs.begin();
+      jobItor != poolJobs.end(); jobItor++) {
+      ASSERT_EQ(ArchivalJobState::PENDING, jobItor->getState());
+      srcUrls.insert(jobItor->getSrcUrl());
+      dstPaths.insert(jobItor->getDstPath());
+    }
+    ASSERT_EQ(1, srcUrls.size());
+    ASSERT_FALSE(srcUrls.find("diskUrl") == srcUrls.end());
+    ASSERT_EQ(1, dstPaths.size());
+    ASSERT_FALSE(dstPaths.find("/grandparent/parent_file") == dstPaths.end());
+  }
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  archive_to_new_file_with_no_storage_class) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl");
+  const std::string dstPath  = "/grandparent/parent_file";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  archive_to_new_file_with_zero_copy_storage_class) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 0;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl");
+  const std::string dstPath  = "/grandparent/parent_file";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, archive_to_new_file_with_no_route) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 1;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  const std::string tapePoolName = "TestTapePool";
+  const uint16_t nbDrives = 1;
+  const uint16_t nbPartialTapes = 1;
+  const std::string tapePoolComment = "Tape-pool comment";
+  ASSERT_NO_THROW(adminApi.createTapePool(requester, tapePoolName, nbDrives,
+    nbPartialTapes, tapePoolComment));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl");
+  const std::string dstPath  = "/grandparent/parent_file";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  archive_to_new_file_with_incomplete_routing) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 2;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  const std::string tapePoolName = "TestTapePool";
+  const uint16_t nbDrives = 1;
+  const uint16_t nbPartialTapes = 1;
+  const std::string tapePoolComment = "Tape-pool comment";
+  ASSERT_NO_THROW(adminApi.createTapePool(requester, tapePoolName, nbDrives,
+    nbPartialTapes, tapePoolComment));
+
+  const uint16_t copyNb = 1;
+  const std::string archiveRouteComment = "Archive-route comment";
+  ASSERT_NO_THROW(adminApi.createArchiveRoute(requester, storageClassName,
+    copyNb, tapePoolName, archiveRouteComment));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl");
+  const std::string dstPath  = "/grandparent/parent_file";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, archive_to_directory) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 1;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  const std::string tapePoolName = "TestTapePool";
+  const uint16_t nbDrives = 1;
+  const uint16_t nbPartialTapes = 1;
+  const std::string tapePoolComment = "Tape-pool comment";
+  ASSERT_NO_THROW(adminApi.createTapePool(requester, tapePoolName, nbDrives,
+    nbPartialTapes, tapePoolComment));
+
+  const uint16_t copyNb = 1;
+  const std::string archiveRouteComment = "Archive-route comment";
+  ASSERT_NO_THROW(adminApi.createArchiveRoute(requester, storageClassName,
+    copyNb, tapePoolName, archiveRouteComment));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl1");
+  srcUrls.push_back("diskUrl2");
+  srcUrls.push_back("diskUrl3");
+  srcUrls.push_back("diskUrl4");
+  const std::string dstPath  = "/grandparent";
+  ASSERT_NO_THROW(userApi.archive(requester, srcUrls, dstPath));
+
+  {
+    DirectoryIterator itor;
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester, "/"));
+    ASSERT_TRUE(itor.hasMore());
+    DirectoryEntry entry;
+    ASSERT_NO_THROW(entry = itor.next());
+    ASSERT_EQ(std::string("grandparent"), entry.getName());
+    ASSERT_EQ(DirectoryEntry::ENTRYTYPE_DIRECTORY, entry.getType());
+    ASSERT_EQ(storageClassName, entry.getStorageClassName());
+  }
+
+  {
+    std::set<std::string> archiveFileNames;
+    DirectoryIterator itor;
+    ASSERT_NO_THROW(itor = userApi.getDirectoryContents(requester,
+      "/grandparent"));
+    while(itor.hasMore()) {
+      const DirectoryEntry entry = itor.next();
+      archiveFileNames.insert(entry.getName());
+    }
+    ASSERT_EQ(4, archiveFileNames.size());
+    ASSERT_TRUE(archiveFileNames.find("diskUrl1") != archiveFileNames.end());
+    ASSERT_TRUE(archiveFileNames.find("diskUrl2") != archiveFileNames.end());
+    ASSERT_TRUE(archiveFileNames.find("diskUrl3") != archiveFileNames.end());
+    ASSERT_TRUE(archiveFileNames.find("diskUrl4") != archiveFileNames.end());
+  }
+
+  {
+    const std::map<TapePool, std::list<ArchivalJob> > allJobs =
+      userApi.getArchivalJobs(requester);
+    ASSERT_EQ(1, allJobs.size());
+    std::map<TapePool, std::list<ArchivalJob> >::const_iterator
+      poolItor = allJobs.begin();
+    ASSERT_FALSE(poolItor == allJobs.end());
+    const TapePool &pool = poolItor->first;
+    ASSERT_TRUE(tapePoolName == pool.getName());
+    const std::list<ArchivalJob> &poolJobs = poolItor->second;
+    ASSERT_EQ(4, poolJobs.size());
+    std::set<std::string> srcUrls;
+    std::set<std::string> dstPaths;
+    for(std::list<ArchivalJob>::const_iterator jobItor = poolJobs.begin();
+      jobItor != poolJobs.end(); jobItor++) {
+      ASSERT_EQ(ArchivalJobState::PENDING, jobItor->getState());
+      srcUrls.insert(jobItor->getSrcUrl());
+      dstPaths.insert(jobItor->getDstPath());
+    }
+    ASSERT_EQ(4, srcUrls.size());
+    ASSERT_FALSE(srcUrls.find("diskUrl1") == srcUrls.end());
+    ASSERT_FALSE(srcUrls.find("diskUrl2") == srcUrls.end());
+    ASSERT_FALSE(srcUrls.find("diskUrl3") == srcUrls.end());
+    ASSERT_FALSE(srcUrls.find("diskUrl4") == srcUrls.end());
+    ASSERT_EQ(4, dstPaths.size());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl1") == srcUrls.end());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl2") == srcUrls.end());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl3") == srcUrls.end());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl4") == srcUrls.end());
+  }
+
+  {
+    const std::list<ArchivalJob> poolJobs = userApi.getArchivalJobs(requester,
+      tapePoolName);
+    ASSERT_EQ(4, poolJobs.size());
+    std::set<std::string> srcUrls;
+    std::set<std::string> dstPaths;
+    for(std::list<ArchivalJob>::const_iterator jobItor = poolJobs.begin();
+      jobItor != poolJobs.end(); jobItor++) {
+      ASSERT_EQ(ArchivalJobState::PENDING, jobItor->getState());
+      srcUrls.insert(jobItor->getSrcUrl());
+      dstPaths.insert(jobItor->getDstPath());
+    }
+    ASSERT_EQ(4, srcUrls.size());
+    ASSERT_FALSE(srcUrls.find("diskUrl1") == srcUrls.end());
+    ASSERT_FALSE(srcUrls.find("diskUrl2") == srcUrls.end());
+    ASSERT_FALSE(srcUrls.find("diskUrl3") == srcUrls.end());
+    ASSERT_FALSE(srcUrls.find("diskUrl4") == srcUrls.end());
+    ASSERT_EQ(4, dstPaths.size());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl1") == srcUrls.end());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl2") == srcUrls.end());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl3") == srcUrls.end());
+    ASSERT_FALSE(dstPaths.find("/grandparent/diskUrl4") == srcUrls.end());
+  }
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  archive_to_directory_without_storage_class) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl1");
+  srcUrls.push_back("diskUrl2");
+  srcUrls.push_back("diskUrl3");
+  srcUrls.push_back("diskUrl4");
+  const std::string dstPath  = "/grandparent";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  archive_to_directory_with_zero_copy_storage_class) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 0;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl1");
+  srcUrls.push_back("diskUrl2");
+  srcUrls.push_back("diskUrl3");
+  srcUrls.push_back("diskUrl4");
+  const std::string dstPath  = "/grandparent";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest, archive_to_directory_with_no_route) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 1;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  const std::string tapePoolName = "TestTapePool";
+  const uint16_t nbDrives = 1;
+  const uint16_t nbPartialTapes = 1;
+  const std::string tapePoolComment = "Tape-pool comment";
+  ASSERT_NO_THROW(adminApi.createTapePool(requester, tapePoolName, nbDrives,
+    nbPartialTapes, tapePoolComment));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl1");
+  srcUrls.push_back("diskUrl2");
+  srcUrls.push_back("diskUrl3");
+  srcUrls.push_back("diskUrl4");
+  const std::string dstPath  = "/grandparent";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+TEST_F(cta_client_SqliteMiddleTierUserTest,
+  archive_to_directory_with_incomplete_routing) {
+  using namespace cta;
+
+  SqliteDatabase db;
+  Vfs vfs;
+  SqliteMiddleTierUser userApi(vfs, db);
+  SqliteMiddleTierAdmin adminApi(vfs, db);
+  const SecurityIdentity requester;
+
+  const std::string storageClassName = "TestStorageClass";
+  const uint16_t nbCopies = 2;
+  const std::string storageClassComment = "Storage-class comment";
+  ASSERT_NO_THROW(adminApi.createStorageClass(requester, storageClassName,
+    nbCopies, storageClassComment));
+
+  const std::string dirPath = "/grandparent";
+  ASSERT_NO_THROW(userApi.createDirectory(requester, dirPath));
+  ASSERT_NO_THROW(userApi.setDirectoryStorageClass(requester, dirPath,
+    storageClassName));
+
+  const std::string tapePoolName = "TestTapePool";
+  const uint16_t nbDrives = 1;
+  const uint16_t nbPartialTapes = 1;
+  const std::string tapePoolComment = "Tape-pool comment";
+  ASSERT_NO_THROW(adminApi.createTapePool(requester, tapePoolName, nbDrives,
+    nbPartialTapes, tapePoolComment));
+
+  const uint16_t copyNb = 1;
+  const std::string archiveRouteComment = "Archive-route comment";
+  ASSERT_NO_THROW(adminApi.createArchiveRoute(requester, storageClassName,
+    copyNb, tapePoolName, archiveRouteComment));
+
+  std::list<std::string> srcUrls;
+  srcUrls.push_back("diskUrl1");
+  srcUrls.push_back("diskUrl2");
+  srcUrls.push_back("diskUrl3");
+  srcUrls.push_back("diskUrl4");
+  const std::string dstPath  = "/grandparent";
+  ASSERT_THROW(userApi.archive(requester, srcUrls, dstPath), std::exception);
+}
+
+} // namespace unitTests
diff --git a/libs/middletier/Vfs.cpp b/libs/middletier/Vfs.cpp
index 68c5441e810fc358bc7bae8479e032fe21863458..2211c757d87859d523031b066b8ff26a484c69e5 100644
--- a/libs/middletier/Vfs.cpp
+++ b/libs/middletier/Vfs.cpp
@@ -71,6 +71,35 @@ void cta::Vfs::checkPathnameDoesNotExist(const std::string &dirPath) {
   }
 }
 
+//------------------------------------------------------------------------------
+// checkStorageClassIsNotInUse
+//------------------------------------------------------------------------------
+void cta::Vfs::checkStorageClassIsNotInUse(const SecurityIdentity &requester, const std::string &storageClass, const std::string &dirPath) {
+  if(getDirectoryStorageClass(requester, dirPath)==storageClass) {
+    std::ostringstream message;
+    message << "checkStorageClassIsNotInUse() - " << dirPath << " has the " << storageClass << " storage class.";
+    throw(Exception(message.str()));
+  }
+  
+  struct dirent *entry;
+  DIR *dp = opendir((m_fsDir+dirPath).c_str());
+  if (dp == NULL) {
+    char buf[256];
+    std::ostringstream message;
+    message << "checkStorageClassIsNotInUse() - opendir " << m_fsDir+dirPath << " error. Reason: \n" << strerror_r(errno, buf, 256);
+    throw(Exception(message.str()));
+  }
+   
+  while((entry = readdir(dp))) {
+    if(entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
+      const std::string dirEntryPathname = dirPath+(entry->d_name);
+      checkStorageClassIsNotInUse(requester, storageClass, dirEntryPathname);
+    }
+  }
+
+  closedir(dp);
+}
+
 //------------------------------------------------------------------------------
 // constructor
 //------------------------------------------------------------------------------
diff --git a/libs/middletier/Vfs.hpp b/libs/middletier/Vfs.hpp
index a87436e93174bd1dff71749219cd5f6a7461e526..e3e57293d66785494d3dc8ba421aa3a39bc6682e 100644
--- a/libs/middletier/Vfs.hpp
+++ b/libs/middletier/Vfs.hpp
@@ -43,6 +43,8 @@ public:
   bool isExistingDirectory(const SecurityIdentity &requester, const std::string &dirPath);
   
   std::string getVidOfFile(const SecurityIdentity &requester, const std::string &pathname, uint16_t copyNb);
+  
+  void checkStorageClassIsNotInUse(const SecurityIdentity &requester, const std::string &storageClass, const std::string &dirPath);
 
 private: