diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1dacac66c9c5865510f8dc92f20428b2fd6f9cae..e3f7b2bca5d6be5020bfbef5a3938d2ecb1c5e0b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,9 @@ cmake_minimum_required (VERSION 2.6)
 
 project(cta)
 
+set(CMAKE_C_FLAGS "-fPIC -pedantic -Wall -Wextra -Werror -Wno-unused-parameter")
+set(CMAKE_CXX_FLAGS "-fPIC -pedantic -Wall -Wextra -Werror -Wno-unused-parameter")
+
 # Explicitly setting the C and C++ compiler flags for the RelWithDebInfo build
 # in order to prevent the -O2 flag from being used.
 set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g")
@@ -26,7 +29,7 @@ set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
 
 add_subdirectory(libs)
-add_subdirectory(unit_tests)
+add_subdirectory(objectstore)
+add_subdirectory(tests)
 add_subdirectory(xroot_clients)
 add_subdirectory(xroot_plugins)
-add_subdirectory(objectstore)
diff --git a/libs/client/CMakeLists.txt b/libs/client/CMakeLists.txt
index e128d00bfd392c59a3b5838f4bd7e7c3d87a0b3e..81dbace149c72de52c2cd6f666f59a52e45b1188 100644
--- a/libs/client/CMakeLists.txt
+++ b/libs/client/CMakeLists.txt
@@ -5,9 +5,10 @@ set (CLIENT_LIB_SRC_FILES
   DirectoryEntry.cpp
   DirectoryIterator.cpp
   Exception.cpp
+  FileAttribute.cpp
   MockClientAPI.cpp
-  MockAPITest.cpp
-  StorageClass.cpp)
+  StorageClass.cpp
+  UserIdentity.cpp)
 
 add_library (ctaclient SHARED
   ${CLIENT_LIB_SRC_FILES})
diff --git a/libs/client/ClientAPI.hpp b/libs/client/ClientAPI.hpp
index 7de9755ac68a09c9718c1403eb7b712a01567f90..92a967c346c708bf1344b502049917a18f5ca3fe 100644
--- a/libs/client/ClientAPI.hpp
+++ b/libs/client/ClientAPI.hpp
@@ -2,7 +2,7 @@
 
 #include "DirectoryIterator.hpp"
 #include "StorageClass.hpp"
-#include "StorageClassList.hpp"
+#include "UserIdentity.hpp"
 
 #include <list>
 #include <stdint.h>
@@ -11,7 +11,8 @@
 namespace cta {
 
 /**
- * Abstract class that specifies the client ClientAPI of the CERN Tape Archive project.
+ * Abstract class that specifies the client ClientAPI of the CERN Tape Archive
+ * project.
  */
 class ClientAPI {
 public:
@@ -21,38 +22,121 @@ public:
    */
   virtual ~ClientAPI() throw() = 0;
 
+  /**
+   * Creates the specified administrator.
+   *
+   * @param requester The identity of the user requesting the creation of the
+   * administrator.
+   * @param admin The identity of the administrator.
+   */
+  virtual void createAdminUser(
+    const UserIdentity &requester,
+    const UserIdentity &admin) = 0;
+
+  /**
+   * Deletes the specified administrator.
+   *
+   * @param requester The identity of the user requesting the deletion of the
+   * administrator.
+   * @param admin The identity of the administrator.
+   */
+  virtual void deleteAdminUser(
+    const UserIdentity &requester,
+    const UserIdentity &admin) = 0;
+
+  /**
+   * Returns the current list of administrators.
+   *
+   * @param requester The identity of the user requesting the list.
+   */
+  virtual std::list<UserIdentity> getAdminUsers(const UserIdentity &requester)
+   const = 0;
+
+  /**
+   * Creates the specified administration host.
+   *
+   * @param requester The identity of the user requesting the creation of the
+   * administration host.
+   * @param adminHost The network name of the administration host.
+   */
+  virtual void createAdminHost(
+    const UserIdentity &requester,
+    const std::string &adminHost) = 0;
+
+  /**
+   * Deletes the specified administration host.
+   *
+   * @param requester The identity of the user requesting the deletion of the
+   * administration host.
+   * @param adminHost The network name of the administration host.
+   */
+  virtual void deleteAdminHost(
+    const UserIdentity &requester,
+    const std::string &adminHost) = 0;
+
+  /**
+   * Returns the current list of administration hosts.
+   *
+   * @param requester The identity of the user requesting the list.
+   */
+  virtual std::list<std::string> getAdminHosts(const UserIdentity &requester)
+   const  = 0;
+
   /**
    * Creates the specified storage class.
    *
+   * @param requester The identity of the user requesting the creation of the
+   * storage class.
    * @param name The name of the storage class.
    * @param nbCopies The number of copies a file associated with this storage
    * class should have on tape.
    */
   virtual void createStorageClass(
+    const UserIdentity &requester,
     const std::string &name,
     const uint8_t nbCopies) = 0;
 
   /**
    * Deletes the specified storage class.
    *
+   * @param requester The identity of the user requesting the deletion of the
+   * storage class.
    * @param name The name of the storage class.
    */
-  virtual void deleteStorageClass(const std::string &name) = 0;
+  virtual void deleteStorageClass(
+    const UserIdentity &requester,
+    const std::string &name) = 0;
 
   /**
    * Gets the current list of storage classes in lexicographical order.
    *
+   * @param requester The identity of the user requesting list.
    * @return The current list of storage classes in lexicographical order.
    */
-  virtual StorageClassList getStorageClasses() const = 0;
+  virtual std::list<StorageClass> getStorageClasses(
+    const UserIdentity &requester) const = 0;
 
   /**
-   * Gets an iterator over the entries of the specified directory.
+   * Creates the specified directory.
    *
+   * @param requester The identity of the user requesting the creation of the
+   * directory.
+   * @param dirPath The full path of the directory.
+   */
+  virtual void createDirectory(
+    const UserIdentity &requester,
+    const std::string &dirPath) = 0;
+
+  /**
+   * Gets the contents of the specified directory.
+   *
+   * @param requester The identity of the user requesting the contents of the
+   * directory.
    * @param dirPath The full path of the directory.
-   * @return The iterator.
+   * @return An iterator over the contents of the directory.
    */
-  virtual DirectoryIterator getDirectoryIterator(
+  virtual DirectoryIterator getDirectoryContents(
+    const UserIdentity &requester,
     const std::string &dirPath) const = 0;
 
   /**
@@ -68,11 +152,14 @@ public:
    * The storage class of the archived file will be inherited from its
    * destination directory.
    *
+   * @param requester The identity of the user requesting the archival.
    * @param srcUrls List of one or more source files.
    * @param dst Destination file or directory within the archive namespace.
    * @return The identifier of the archive job.
    */
-  virtual std::string archiveToTape(const std::list<std::string> &srcUrls,
+  virtual std::string archiveToTape(
+    const UserIdentity &requester,
+    const std::list<std::string> &srcUrls,
     std::string dst) = 0;
 
 }; // class ClientAPI
diff --git a/libs/client/DirectoryEntry.cpp b/libs/client/DirectoryEntry.cpp
index 27f03539f9d75aeec825be3bd587557ee2d05cd4..74041e52db9b75231b30187438d1b106d34c7b91 100644
--- a/libs/client/DirectoryEntry.cpp
+++ b/libs/client/DirectoryEntry.cpp
@@ -1 +1,26 @@
 #include "DirectoryEntry.hpp"
+
+//------------------------------------------------------------------------------
+// typeToString
+//------------------------------------------------------------------------------
+const char *cta::DirectoryEntry::typeToString(const EntryType enumValue)
+  throw() {
+  switch(enumValue) {
+  case NONE           : return "NONE";
+  case FILE_ENTRY     : return "FILE_ENTRY";
+  case DIRECTORY_ENTRY: return "DIRECTORY_ENTRY";
+  default             : return "UNKNOWN";
+  }
+}
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+cta::DirectoryEntry::DirectoryEntry():
+  entryType(NONE),
+  ownerId(0),
+  groupId(0),
+  ownerPerms(0),
+  groupPerms(0),
+  otherPerms(0) {
+}
diff --git a/libs/client/DirectoryEntry.hpp b/libs/client/DirectoryEntry.hpp
index 25269a0ba2286dedaf28b2af7445a68f2d99e921..86e0c189c5809724738016e0db062cbed3e28bfa 100644
--- a/libs/client/DirectoryEntry.hpp
+++ b/libs/client/DirectoryEntry.hpp
@@ -1,11 +1,87 @@
 #pragma once
 
+#include "FileAttribute.hpp"
+
+#include <list>
+#include <stdint.h>
 #include <string>
 
 namespace cta {
 
+/**
+ * The structure of a directory entry.
+ */
 struct DirectoryEntry {
+
+  /**
+   * Enumeration of the different types of directory entry.
+   */
+  enum EntryType {
+    NONE,
+    FILE_ENTRY,
+    DIRECTORY_ENTRY
+  };
+
+  /**
+   * Thread safe method that returns the string representation of the
+   * specified enumeration (integer) value.
+   *
+   * @param enumValue The enumeration (integer) value.
+   * @return The string value.
+   */
+  static const char *typeToString(const EntryType enumValue) throw();
+
+  /**
+   * The type of the directory entry.
+   */
+  EntryType entryType;
+
+  /**
+   * The name of the directory.
+   */
   std::string name;
+
+  /**
+   * The user ID of the file's owner.
+   */
+  uint32_t ownerId;
+
+  /**
+   * The group ID of the file.
+   */
+  uint32_t groupId;
+
+  /**
+   * Access permissions for the file's owner "a la" posix. For example a value
+   * of 7 means read, write and execute permissions.
+   */
+  uint8_t ownerPerms;
+
+  /**
+   * Access permissions for the file's group  "a la" posix. For example a
+   * value of 7 means read, write and execute permissions.
+   */
+  uint8_t groupPerms;
+
+  /**
+   * Access permissions for users other than the owner or members of the file's
+   * group.
+   */
+  uint8_t otherPerms;
+
+  /**
+   * The attributes of the directory.
+   */
+  std::list<FileAttribute> attributes;
+
+  /**
+   * Constructor.
+   *
+   * Initialises the entry type of the DirectoryEntry to NONE and all integer
+   * member-variables to 0.
+   */
+  DirectoryEntry();
+
 }; // DirectoryEntry
 
 } // namespace cta
diff --git a/libs/client/DirectoryIterator.cpp b/libs/client/DirectoryIterator.cpp
index 85bafa9388215b5b5f04c42d7c84a6666d1f7600..dbff1d5e3112f5fb722cba28bf9ff03114a5bdd1 100644
--- a/libs/client/DirectoryIterator.cpp
+++ b/libs/client/DirectoryIterator.cpp
@@ -1,4 +1,11 @@
 #include "DirectoryIterator.hpp"
+#include "Exception.hpp"
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+cta::DirectoryIterator::DirectoryIterator() {
+}
 
 //------------------------------------------------------------------------------
 // constructor
@@ -12,3 +19,23 @@ cta::DirectoryIterator::DirectoryIterator(
 //------------------------------------------------------------------------------
 cta::DirectoryIterator::~DirectoryIterator() throw() {
 }
+
+//------------------------------------------------------------------------------
+// hasMore
+//------------------------------------------------------------------------------
+bool cta::DirectoryIterator::hasMore() {
+  return !m_entries.empty();
+}
+
+//------------------------------------------------------------------------------
+// next
+//------------------------------------------------------------------------------
+const cta::DirectoryEntry cta::DirectoryIterator::next() {
+  if(m_entries.empty()) {
+    throw Exception("Out of bounds: There are no more directory entries");
+  }
+
+  DirectoryEntry entry = m_entries.front();
+  m_entries.pop_front();
+  return entry;
+}
diff --git a/libs/client/DirectoryIterator.hpp b/libs/client/DirectoryIterator.hpp
index 5fdaf83533db887abe305665bfc1e1818f24b667..232efa492abcfa41700c920dacd7c8cdcf225442 100644
--- a/libs/client/DirectoryIterator.hpp
+++ b/libs/client/DirectoryIterator.hpp
@@ -23,6 +23,11 @@ namespace cta {
 class DirectoryIterator {
 public:
 
+  /**
+   * Constructor.
+   */
+  DirectoryIterator();
+
   /**
    * Constructor.
    *
diff --git a/libs/client/FileAttribute.cpp b/libs/client/FileAttribute.cpp
index d934deb9c14ce20c3cfbe3824609f59f8a53cd83..84432ac75c2197652070f75c8e54c1c83308f7a7 100644
--- a/libs/client/FileAttribute.cpp
+++ b/libs/client/FileAttribute.cpp
@@ -3,12 +3,12 @@
 //------------------------------------------------------------------------------
 // constructor
 //------------------------------------------------------------------------------
-cta::FileAtribute::FileAtribute() {
+cta::FileAttribute::FileAttribute() {
 }
 
 //------------------------------------------------------------------------------
 // constructor
 //------------------------------------------------------------------------------
-cta::FileAtribute::FileAtribute(const std::string &name,
+cta::FileAttribute::FileAttribute(const std::string &name,
   const std::string &value): name(name), value(value) {
 }
diff --git a/libs/client/FileAttribute.hpp b/libs/client/FileAttribute.hpp
index 6b8f1d927424f57d7b28a90154abe831de9a8d7c..299913948f37cecd1e75ea0786cc9efab0212529 100644
--- a/libs/client/FileAttribute.hpp
+++ b/libs/client/FileAttribute.hpp
@@ -7,7 +7,7 @@ namespace cta {
 /**
  * Class representing a file atrribute.
  */
-struct FileAtribute {
+struct FileAttribute {
 
   /**
    * The name of the attribute.
@@ -22,7 +22,7 @@ struct FileAtribute {
   /**
    * Constructor.
    */
-  FileAtribute();
+  FileAttribute();
 
   /**
    * Constructor.
@@ -30,8 +30,8 @@ struct FileAtribute {
    * @param name The name of the attribute.
    * @param value value of the attribute.
    */
-  FileAtribute(const std::string &name, const std::string &value);
+  FileAttribute(const std::string &name, const std::string &value);
 
-}; // struct FileAtribute
+}; // struct FileAttribute
 
 } // namespace cta
diff --git a/libs/client/MockAPITest.cpp b/libs/client/MockAPITest.cpp
deleted file mode 100644
index 441bc29d823f2bd4161b725d41e318e0850ddb9e..0000000000000000000000000000000000000000
--- a/libs/client/MockAPITest.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-#include "MockClientAPI.hpp"
-
-#include <gtest/gtest.h>
-
-namespace unitTests {
-
-class cta_client_MockClientAPITest: public ::testing::Test {
-protected:
-
-  virtual void SetUp() {
-  }
-
-  virtual void TearDown() {
-  }
-};
-
-TEST_F(cta_client_MockClientAPITest, createStorageClass_new) {
-  using namespace cta;
-
-  MockClientAPI api;
-
-  ASSERT_TRUE(api.getStorageClasses().empty());
-
-  const std::string name = "TestStorageClass";
-  const uint8_t nbCopies = 2;
-  ASSERT_NO_THROW(api.createStorageClass(name, nbCopies));
-
-  ASSERT_EQ(1, api.getStorageClasses().size());
-  cta::StorageClass storageClass;
-  ASSERT_NO_THROW(storageClass = api.getStorageClasses().front());
-  ASSERT_EQ(name, storageClass.name);
-  ASSERT_EQ(nbCopies, storageClass.nbCopies);
-}
-
-TEST_F(cta_client_MockClientAPITest, createStorageClass_already_existing) {
-  using namespace cta;
-
-  MockClientAPI api;
-
-  ASSERT_TRUE(api.getStorageClasses().empty());
-  
-  const std::string name = "TestStorageClass";
-  const uint8_t nbCopies = 2;
-  ASSERT_NO_THROW(api.createStorageClass(name, nbCopies));
-  
-  ASSERT_EQ(1, api.getStorageClasses().size());
-  cta::StorageClass storageClass;
-  ASSERT_NO_THROW(storageClass = api.getStorageClasses().front());
-  ASSERT_EQ(name, storageClass.name);
-  ASSERT_EQ(nbCopies, storageClass.nbCopies);
-
-  ASSERT_THROW(api.createStorageClass(name, nbCopies), std::exception);
-}
-
-TEST_F(cta_client_MockClientAPITest, createStorageClass_lexicographical_order) {
-  using namespace cta;
-
-  MockClientAPI api;
-
-  ASSERT_TRUE(api.getStorageClasses().empty());
-  
-  ASSERT_NO_THROW(api.createStorageClass("d", 1));
-  ASSERT_NO_THROW(api.createStorageClass("b", 1));
-  ASSERT_NO_THROW(api.createStorageClass("a", 1));
-  ASSERT_NO_THROW(api.createStorageClass("c", 1));
-  
-  ASSERT_EQ(4, api.getStorageClasses().size());
-
-  cta::StorageClassList storageClasses = api.getStorageClasses();
-
-  ASSERT_EQ(std::string("a"), storageClasses.front().name);
-  storageClasses.pop_front();
-  ASSERT_EQ(std::string("b"), storageClasses.front().name);
-  storageClasses.pop_front();
-  ASSERT_EQ(std::string("c"), storageClasses.front().name);
-  storageClasses.pop_front();
-  ASSERT_EQ(std::string("d"), storageClasses.front().name);
-}
-
-TEST_F(cta_client_MockClientAPITest, deleteStorageClass_existing) {
-  using namespace cta;
-
-  MockClientAPI api;
-
-  ASSERT_TRUE(api.getStorageClasses().empty());
-  
-  const std::string name = "TestStorageClass";
-  const uint8_t nbCopies = 2;
-  ASSERT_NO_THROW(api.createStorageClass(name, nbCopies));
-  
-  ASSERT_EQ(1, api.getStorageClasses().size());
-  cta::StorageClass storageClass;
-  ASSERT_NO_THROW(storageClass = api.getStorageClasses().front());
-  ASSERT_EQ(name, storageClass.name);
-  ASSERT_EQ(nbCopies, storageClass.nbCopies);
-
-  ASSERT_NO_THROW(api.deleteStorageClass(name));
-
-  ASSERT_TRUE(api.getStorageClasses().empty());
-}
-
-TEST_F(cta_client_MockClientAPITest, deleteStorageClass_non_existing) {
-  using namespace cta;
-
-  MockClientAPI api;
-
-  ASSERT_TRUE(api.getStorageClasses().empty());
-
-  const std::string name = "TestStorageClass";
-  ASSERT_THROW(api.deleteStorageClass(name), std::exception);
-
-  ASSERT_TRUE(api.getStorageClasses().empty());
-}
-
-TEST_F(cta_client_MockClientAPITest, getDirectoryIterator_empty) {
-  using namespace cta;
-
-  MockClientAPI api;
-
-  ASSERT_NO_THROW(api.getDirectoryIterator("/"));
-}
-
-} // namespace unitTests
diff --git a/libs/client/MockClientAPI.cpp b/libs/client/MockClientAPI.cpp
index b7ca0d1468259ec7179968d33d4e05bef67837e8..f39d9e8ffe0bdadaf7b1516a22ac573e9b24c41d 100644
--- a/libs/client/MockClientAPI.cpp
+++ b/libs/client/MockClientAPI.cpp
@@ -1,5 +1,5 @@
-#include "MockClientAPI.hpp"
 #include "Exception.hpp"
+#include "MockClientAPI.hpp"
 
 #include <sstream>
 
@@ -15,11 +15,59 @@ cta::MockClientAPI::MockClientAPI() {
 cta::MockClientAPI::~MockClientAPI() throw() {
 }
 
+//------------------------------------------------------------------------------
+// createAdminUser
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::createAdminUser(
+  const UserIdentity &requester,
+  const UserIdentity &admin) {
+}
+  
+//------------------------------------------------------------------------------
+// deleteAdminUser
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::deleteAdminUser(
+  const UserIdentity &requester,
+  const UserIdentity &admin) {
+}
+  
+//------------------------------------------------------------------------------
+// getAdminUsers
+//------------------------------------------------------------------------------
+std::list<cta::UserIdentity> cta::MockClientAPI::getAdminUsers(
+  const UserIdentity &requester) const {
+  return m_adminUsers;
+}
+
+//------------------------------------------------------------------------------
+// createAdminHost
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::createAdminHost(
+  const UserIdentity &requester,
+  const std::string &adminHost) {
+}
+
+//------------------------------------------------------------------------------
+// deleteAdminHost
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::deleteAdminHost(
+  const UserIdentity &requester,
+  const std::string &adminHost) {
+}
+  
+//------------------------------------------------------------------------------
+// getAdminHosts
+//------------------------------------------------------------------------------
+std::list<std::string> cta::MockClientAPI::getAdminHosts(
+  const UserIdentity &requester) const {
+  return m_adminHosts;
+}
+
 //------------------------------------------------------------------------------
 // createStorageClass
 //------------------------------------------------------------------------------
-void cta::MockClientAPI::createStorageClass(const std::string &name,
-  const uint8_t nbCopies) {
+void cta::MockClientAPI::createStorageClass(const UserIdentity &requester,
+  const std::string &name, const uint8_t nbCopies) {
   try {
     checkStorageClassDoesNotAlreadyExist(name);
     StorageClass storageClass(name, nbCopies);
@@ -47,7 +95,8 @@ void cta::MockClientAPI::checkStorageClassDoesNotAlreadyExist(
 //------------------------------------------------------------------------------
 // deleteStorageClass
 //------------------------------------------------------------------------------
-void cta::MockClientAPI::deleteStorageClass(const std::string &name) {
+void cta::MockClientAPI::deleteStorageClass(const UserIdentity &requester,
+  const std::string &name) {
   try {
     checkStorageClassExists(name);
     m_storageClasses.erase(name);
@@ -74,7 +123,8 @@ void cta::MockClientAPI::checkStorageClassExists(
 //------------------------------------------------------------------------------
 // getStorageClasses
 //------------------------------------------------------------------------------
-std::list<cta::StorageClass> cta::MockClientAPI::getStorageClasses() const {
+std::list<cta::StorageClass> cta::MockClientAPI::getStorageClasses(
+  const UserIdentity &requester) const {
   std::list<StorageClass> storageClasses;
   for(std::map<std::string, StorageClass>::const_iterator itor =
     m_storageClasses.begin(); itor != m_storageClasses.end(); itor++) {
@@ -84,11 +134,107 @@ std::list<cta::StorageClass> cta::MockClientAPI::getStorageClasses() const {
 }
 
 //------------------------------------------------------------------------------
-// getDirectoryIterator
+// createDirectory
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::createDirectory(const UserIdentity &requester,
+  const std::string &dirPath) {
+  checkAbsolutePathSyntax(dirPath);
+}
+
+//------------------------------------------------------------------------------
+// checkAbsolutePathSyntax
 //------------------------------------------------------------------------------
-cta::DirectoryIterator cta::MockClientAPI::
-  getDirectoryIterator(const std::string &dirPath) const {
+void cta::MockClientAPI::checkAbsolutePathSyntax(const std::string &path) {
+  try {
+    checkPathStartsWithASlash(path);
+    checkPathContainsValidChars(path);
+    checkPathDoesContainConsecutiveSlashes(path);
+  } catch(std::exception &ex) {
+    std::ostringstream message;
+    message << "Absolute path \"" << path << "\" contains a syntax error: " <<
+      ex.what();
+    throw Exception(message.str());
+  }
+}
 
+//------------------------------------------------------------------------------
+// checkPathStartsWithASlash
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::checkPathStartsWithASlash(const std::string &path) {
+  if(path.empty()) {
+    throw Exception("Path is an empty string");
+  }
+
+  if('/' != path[0]) {
+    throw Exception("Path does not start with a '/' character");
+  }
+}
+
+//------------------------------------------------------------------------------
+// checkPathContainsValidChars
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::checkPathContainsValidChars(const std::string &path) {
+  for(std::string::const_iterator itor = path.begin(); itor != path.end();
+    itor++) {
+    checkValidPathChar(*itor);
+  }
+}
+
+//------------------------------------------------------------------------------
+// checkValidPathChar
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::checkValidPathChar(const char c) {
+  if(!isValidPathChar(c)) {
+    std::ostringstream message;
+    message << "The '" << c << "' character cannot be used within a path";
+    throw Exception(message.str());
+  }
+}
+
+//------------------------------------------------------------------------------
+// isValidPathChar
+//------------------------------------------------------------------------------
+bool cta::MockClientAPI::isValidPathChar(const char c) {
+  return ('0' <= c && c <= '9') ||
+         ('A' <= c && c <= 'Z') ||
+         ('a' <= c && c <= 'z') ||
+         c == '_'               ||
+         c == '/';
+}
+
+//------------------------------------------------------------------------------
+// checkPathDoesContainConsecutiveSlashes
+//------------------------------------------------------------------------------
+void cta::MockClientAPI::checkPathDoesContainConsecutiveSlashes(
+  const std::string &path) {
+  char previousChar = '\0';
+
+  for(std::string::const_iterator itor = path.begin(); itor != path.end();
+    itor++) {
+    const char &currentChar  = *itor;
+    if(previousChar == '/' && currentChar == '/') {
+      throw Exception("Path contains consecutive slashes");
+    }
+    previousChar = currentChar;
+  }
+}
+
+//------------------------------------------------------------------------------
+// getEnclosingDirPath
+//------------------------------------------------------------------------------
+std::string cta::MockClientAPI::getEnclosingDirPath(const std::string &path) {
+  const std::string::size_type last_slash_idx = path.find_last_of('/');
+  if(std::string::npos == last_slash_idx) {
+    throw Exception("Path does not contain a slash");
+  }
+  return path.substr(0, last_slash_idx);
+}
+
+//------------------------------------------------------------------------------
+// getDirectoryContents
+//------------------------------------------------------------------------------
+cta::DirectoryIterator cta::MockClientAPI::getDirectoryContents(
+  const UserIdentity &requester, const std::string &dirPath) const {
   std::list<DirectoryEntry> entries;
   DirectoryIterator itor(entries);
   return itor;
@@ -97,7 +243,7 @@ cta::DirectoryIterator cta::MockClientAPI::
 //------------------------------------------------------------------------------
 // archiveToTape
 //------------------------------------------------------------------------------
-std::string cta::MockClientAPI::archiveToTape(
+std::string cta::MockClientAPI::archiveToTape(const UserIdentity &requester,
   const std::list<std::string> &srcUrls, std::string dst) {
   return "Funny_Job_ID";
 }
diff --git a/libs/client/MockClientAPI.hpp b/libs/client/MockClientAPI.hpp
index 1e115f959f6f55ce87501677af1ac3daa7e6cc1d..324e8482d976bca6d045b5a41518f0f3c6541c35 100644
--- a/libs/client/MockClientAPI.hpp
+++ b/libs/client/MockClientAPI.hpp
@@ -22,38 +22,119 @@ public:
    */
   ~MockClientAPI() throw();
 
+  /**
+   * Creates the specified administrator.
+   *
+   * @param requester The identity of the user requesting the creation of the
+   * administrator.
+   * @param admin The identity of the administrator.
+   */
+  void createAdminUser(
+    const UserIdentity &requester,
+    const UserIdentity &admin);
+
+  /**
+   * Deletes the specified administrator.
+   *
+   * @param requester The identity of the user requesting the deletion of the
+   * administrator.
+   * @param admin The identity of the administrator.
+   */
+  void deleteAdminUser(
+    const UserIdentity &requester,
+    const UserIdentity &admin);
+
+  /**
+   * Returns the current list of administrators.
+   *
+   * @param requester The identity of the user requesting the list.
+   */
+  std::list<UserIdentity> getAdminUsers(const UserIdentity &requester) const;
+
+  /**
+   * Creates the specified administration host.
+   *
+   * @param requester The identity of the user requesting the creation of the
+   * administration host.
+   * @param adminHost The network name of the administration host.
+   */
+  void createAdminHost(
+    const UserIdentity &requester,
+    const std::string &adminHost);
+
+  /**
+   * Deletes the specified administration host.
+   *
+   * @param requester The identity of the user requesting the deletion of the
+   * administration host.
+   * @param adminHost The network name of the administration host.
+   */
+  void deleteAdminHost(
+    const UserIdentity &requester,
+    const std::string &adminHost);
+
+  /**
+   * Returns the current list of administration hosts.
+   *
+   * @param requester The identity of the user requesting the list.
+   */
+  std::list<std::string> getAdminHosts(const UserIdentity &requester) const;
+
   /**
    * Creates the specified storage class.
    *
+   * @param requester The identity of the user requesting the creation of the
+   * storage class.
    * @param name The name of the storage class.
    * @param nbCopies The number of copies a file associated with this storage
    * class should have on tape.
    */
   void createStorageClass(
+    const UserIdentity &requester,
     const std::string &name,
     const uint8_t nbCopies);
 
   /**
    * Deletes the specified storage class.
    *
+   * @param requester The identity of the user requesting the deletion of the
+   * storage class.
    * @param name The name of the storage class.
    */
-  void deleteStorageClass(const std::string &name);
+  void deleteStorageClass(
+    const UserIdentity &requester,
+    const std::string &name);
 
   /**
    * Gets the current list of storage classes in lexicographical order.
    *
+   * @param requester The identity of the user requesting the list.
    * @return The current list of storage classes in lexicographical order.
    */
-  StorageClassList getStorageClasses() const;
+  std::list<StorageClass> getStorageClasses(
+    const UserIdentity &requester) const;
 
   /**
-   * Gets an iterator over the entries of the specified directory.
+   * Creates the specified directory.
    *
+   * @param requester The identity of the user requesting the creation of the
+   * directory.
    * @param dirPath The full path of the directory.
-   * @return The iterator.
    */
-  DirectoryIterator getDirectoryIterator(
+  void createDirectory(
+    const UserIdentity &requester,
+    const std::string &dirPath);
+
+  /**
+   * Gets the contents of the specified directory.
+   *
+   * @param requester The identity of the user requesting the contents of the
+   * directory.
+   * @param dirPath The full path of the directory.
+   * @return An iterator over the contents of the directory.
+   */
+  DirectoryIterator getDirectoryContents(
+    const UserIdentity &requester,
     const std::string &dirPath) const;
 
   /**
@@ -69,14 +150,27 @@ public:
    * The storage class of the archived file will be inherited from its
    * destination directory.
    *
+   * @param requester The identity of the user requesting the archival.
    * @param srcUrls List of one or more source files.
    * @param dst Destination file or directory within the archive namespace.
    * @return The identifier of the archive job.
    */
-  std::string archiveToTape(const std::list<std::string> &srcUrls,
+  std::string archiveToTape(
+    const UserIdentity &requester,
+    const std::list<std::string> &srcUrls,
     std::string dst);
 
-private:
+protected:
+
+  /**
+   * The current list of administrators.
+   */
+  std::list<UserIdentity> m_adminUsers;
+
+  /**
+   * The current list of administration hosts.
+   */
+  std::list<std::string> m_adminHosts;
 
   /**
    * The current list of storage classes.
@@ -93,10 +187,69 @@ private:
   /**
    * Throws an exception if the specified storage class does not exist.
    *
-   * @param name The name of teh storage class.
+   * @param name The name of the storage class.
    */
   void checkStorageClassExists(const std::string &name) const;
 
+  /**
+   * Throws an exception if the specified absolute path constains a
+   * syntax error.
+   *
+   * @param path The Absolute path.
+   */
+  void checkAbsolutePathSyntax(const std::string &path);
+
+  /**
+   * Throws an exception if the specified path does not start with a slash.
+   *
+   * @param path The path.
+   */
+  void checkPathStartsWithASlash(const std::string &path);
+
+  /**
+   * Throws an exception if the specified path does not contain valid
+   * characters.
+   *
+   * @param path The path.
+   */
+  void checkPathContainsValidChars(const std::string &path);
+
+  /**
+   * Throws an exception if the specified character cannot be used within a
+   * path.
+   *
+   * @param c The character to be tested.
+   */
+  void checkValidPathChar(const char c);
+
+  /**
+   * Returns true of the specified character can be used within a path.
+   */
+  bool isValidPathChar(const char c);
+
+  /**
+   * Throws an exception if the specified path contains consective slashes.  For
+   * example the path "/just_before_consectuive_slashes//file" would cause this
+   * method to throw an exception.
+   *
+   * @param path The path.
+   */
+  void checkPathDoesContainConsecutiveSlashes(const std::string &path);
+
+  /**
+   * Returns the path of the enclosing directory of the specified path.
+   *
+   * For example:
+   *
+   * * path="/grandparent/parent/child" would return "/grandparent/parent"
+   * * path="/grandparent" would return "/grandparent"
+   * * path="/" would return "" where empty string means no enclosing directoyr
+   *
+   * @param path The path.
+   * @return The path of the enclosing directory.
+   */
+  std::string getEnclosingDirPath(const std::string &path);
+
 }; // class MockClientAPI
 
 } // namespace cta
diff --git a/libs/client/MockClientAPITest.cpp b/libs/client/MockClientAPITest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f06e71693005d8a44cc19f4bd669abffbd30a4f
--- /dev/null
+++ b/libs/client/MockClientAPITest.cpp
@@ -0,0 +1,428 @@
+#include "TestingMockClientAPI.hpp"
+
+#include <gtest/gtest.h>
+
+namespace unitTests {
+
+class cta_client_MockClientAPITest: public ::testing::Test {
+protected:
+
+  virtual void SetUp() {
+  }
+
+  virtual void TearDown() {
+  }
+};
+
+TEST_F(cta_client_MockClientAPITest, createAdminUser_new) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_TRUE(adminUsers.empty());
+  }
+
+  const uint16_t adminUser1Uid = 1234;
+  const uint16_t adminUser1Gid = 5678;
+  const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, "");
+  ASSERT_NO_THROW(api.createAdminUser(requester, adminUser1));
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_EQ(1, adminUsers.size());
+
+    ASSERT_EQ(adminUser1Uid, adminUsers.front().uid);
+    ASSERT_EQ(adminUser1Gid, adminUsers.front().gid);
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, createAdminUser_already_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_TRUE(adminUsers.empty());
+  }
+
+  const uint16_t adminUser1Uid = 1234;
+  const uint16_t adminUser1Gid = 5678;
+  const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, "");
+  ASSERT_NO_THROW(api.createAdminUser(requester, adminUser1));
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_EQ(1, adminUsers.size());
+
+    ASSERT_EQ(adminUser1Uid, adminUsers.front().uid);
+    ASSERT_EQ(adminUser1Gid, adminUsers.front().gid);
+  }
+
+  ASSERT_THROW(api.createAdminUser(requester, adminUser1), std::exception);
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_EQ(1, adminUsers.size());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, deleteAdminUser_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_TRUE(adminUsers.empty());
+  }
+
+  const uint16_t adminUser1Uid = 1234;
+  const uint16_t adminUser1Gid = 5678;
+  const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, "");
+  ASSERT_NO_THROW(api.createAdminUser(requester, adminUser1));
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_EQ(1, adminUsers.size());
+
+    ASSERT_EQ(adminUser1Uid, adminUsers.front().uid);
+    ASSERT_EQ(adminUser1Gid, adminUsers.front().gid);
+  }
+
+  ASSERT_NO_THROW(api.deleteAdminUser(requester, adminUser1));
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_TRUE(adminUsers.empty());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, deleteAdminUser_non_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_TRUE(adminUsers.empty());
+  } 
+  
+  const uint16_t adminUser1Uid = 1234;
+  const uint16_t adminUser1Gid = 5678;
+  const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, "");
+  ASSERT_THROW(api.deleteAdminUser(requester, adminUser1), std::exception);
+
+  {
+    std::list<UserIdentity> adminUsers;
+    ASSERT_NO_THROW(adminUsers = api.getAdminUsers(requester));
+    ASSERT_TRUE(adminUsers.empty());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, createAdminHost_new) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<std::string> adminHosts;
+    ASSERT_NO_THROW(adminHosts = api.getAdminHosts(requester));
+    ASSERT_TRUE(adminHosts.empty());
+  }
+
+  const std::string adminHost1 = "adminHost1";
+  ASSERT_NO_THROW(api.createAdminHost(requester, adminHost1));
+
+  {
+    std::list<std::string> adminHosts;
+    ASSERT_NO_THROW(adminHosts = api.getAdminHosts(requester));
+    ASSERT_EQ(1, adminHosts.size());
+
+    ASSERT_EQ(adminHost1, adminHosts.front());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, deleteAdminHost_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<std::string> adminHosts;
+    ASSERT_NO_THROW(adminHosts = api.getAdminHosts(requester));
+    ASSERT_TRUE(adminHosts.empty());
+  }
+
+  const std::string adminHost1 = "adminHost1";
+  ASSERT_NO_THROW(api.createAdminHost(requester, adminHost1));
+
+  {
+    std::list<std::string> adminHosts;
+    ASSERT_NO_THROW(adminHosts = api.getAdminHosts(requester));
+    ASSERT_EQ(1, adminHosts.size());
+
+    ASSERT_EQ(adminHost1, adminHosts.front());
+  }
+
+  ASSERT_NO_THROW(api.deleteAdminHost(requester, adminHost1));
+
+  {
+    std::list<std::string> adminHosts;
+    ASSERT_NO_THROW(adminHosts = api.getAdminHosts(requester));
+    ASSERT_TRUE(adminHosts.empty());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, deleteAdminHost_non_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+  
+  {
+    std::list<std::string> adminHosts;
+    ASSERT_NO_THROW(adminHosts = api.getAdminHosts(requester));
+    ASSERT_TRUE(adminHosts.empty());
+  }
+
+  const std::string adminHost1 = "adminHost1";
+  ASSERT_THROW(api.deleteAdminHost(requester, adminHost1), std::exception);
+
+  {
+    std::list<std::string> adminHosts;
+    ASSERT_NO_THROW(adminHosts = api.getAdminHosts(requester));
+    ASSERT_TRUE(adminHosts.empty());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, createStorageClass_new) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_TRUE(storageClasses.empty());
+  }
+
+  const std::string name = "TestStorageClass";
+  const uint8_t nbCopies = 2;
+  ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies));
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_EQ(1, storageClasses.size());
+
+    StorageClass storageClass;
+    ASSERT_NO_THROW(storageClass = storageClasses.front());
+    ASSERT_EQ(name, storageClass.name);
+    ASSERT_EQ(nbCopies, storageClass.nbCopies);
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, createStorageClass_already_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_TRUE(storageClasses.empty());
+  }
+
+  const std::string name = "TestStorageClass";
+  const uint8_t nbCopies = 2;
+  ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies));
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_EQ(1, storageClasses.size());
+
+    StorageClass storageClass;
+    ASSERT_NO_THROW(storageClass = storageClasses.front());
+    ASSERT_EQ(name, storageClass.name);
+    ASSERT_EQ(nbCopies, storageClass.nbCopies);
+  }
+  
+  ASSERT_THROW(api.createStorageClass(requester, name, nbCopies),
+    std::exception);
+}
+
+TEST_F(cta_client_MockClientAPITest, createStorageClass_lexicographical_order) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_TRUE(storageClasses.empty());
+  }
+
+  ASSERT_NO_THROW(api.createStorageClass(requester, "d", 1));
+  ASSERT_NO_THROW(api.createStorageClass(requester, "b", 1));
+  ASSERT_NO_THROW(api.createStorageClass(requester, "a", 1));
+  ASSERT_NO_THROW(api.createStorageClass(requester, "c", 1));
+  
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_EQ(4, storageClasses.size());
+
+    ASSERT_EQ(std::string("a"), storageClasses.front().name);
+    storageClasses.pop_front();
+    ASSERT_EQ(std::string("b"), storageClasses.front().name);
+    storageClasses.pop_front();
+    ASSERT_EQ(std::string("c"), storageClasses.front().name);
+    storageClasses.pop_front();
+    ASSERT_EQ(std::string("d"), storageClasses.front().name);
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, deleteStorageClass_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_TRUE(storageClasses.empty());
+  }
+
+  const std::string name = "TestStorageClass";
+  const uint8_t nbCopies = 2;
+  ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies));
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_EQ(1, storageClasses.size());
+  
+    StorageClass storageClass;
+    ASSERT_NO_THROW(storageClass = storageClasses.front());
+    ASSERT_EQ(name, storageClass.name);
+    ASSERT_EQ(nbCopies, storageClass.nbCopies);
+
+    ASSERT_NO_THROW(api.deleteStorageClass(requester, name));
+  }
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_TRUE(storageClasses.empty());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, deleteStorageClass_non_existing) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_TRUE(storageClasses.empty());
+  }
+
+  const std::string name = "TestStorageClass";
+  ASSERT_THROW(api.deleteStorageClass(requester, name), std::exception);
+
+  {
+    std::list<StorageClass> storageClasses;
+    ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester));
+    ASSERT_TRUE(storageClasses.empty());
+  }
+}
+
+TEST_F(cta_client_MockClientAPITest, getDirectoryContents_root_dir_is_empty) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+  const std::string dirPath = "/";
+
+  DirectoryIterator itor;
+  ASSERT_NO_THROW(itor = api.getDirectoryContents(requester,"/"));
+  ASSERT_FALSE(itor.hasMore());
+}
+
+TEST_F(cta_client_MockClientAPITest, createDirectory_empty_string) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+  const std::string dirPath = "";
+
+  ASSERT_THROW(api.createDirectory(requester, dirPath), std::exception);
+}
+
+TEST_F(cta_client_MockClientAPITest, createDirectory_consecutive_slashes) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+  const std::string dirPath = "//";
+
+  ASSERT_THROW(api.createDirectory(requester, dirPath), std::exception);
+}
+
+TEST_F(cta_client_MockClientAPITest, createDirectory_invalid_chars) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+  const std::string dirPath = "/grandparent/?parent";
+  
+  ASSERT_THROW(api.createDirectory(requester, dirPath), std::exception);
+}
+
+TEST_F(cta_client_MockClientAPITest, createDirectory_top_level) {
+  using namespace cta;
+
+  TestingMockClientAPI api;
+  const UserIdentity requester;
+  const std::string dirPath = "/grandparent";
+  
+  ASSERT_NO_THROW(api.createDirectory(requester, dirPath));
+
+  DirectoryIterator itor;
+
+  ASSERT_NO_THROW(itor = api.getDirectoryContents(requester, "/"));
+
+  ASSERT_TRUE(itor.hasMore());
+
+  DirectoryEntry entry;
+
+  ASSERT_NO_THROW(entry = itor.next());
+
+  ASSERT_EQ(std::string("grandparent"), entry.name);
+}
+
+} // namespace unitTests
diff --git a/libs/client/StorageClassList.hpp b/libs/client/StorageClassList.hpp
deleted file mode 100644
index 3e24d1be0fb1e51f2ce5b5d85521fed0b0ed5177..0000000000000000000000000000000000000000
--- a/libs/client/StorageClassList.hpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include "StorageClass.hpp"
-
-#include <list>
-
-namespace cta {
-
-typedef std::list<StorageClass> StorageClassList;
-
-} // namespace cta
diff --git a/libs/client/UserIdentity.cpp b/libs/client/UserIdentity.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..66a02e5d4e3ec071a51a4bd437678ec6f97d1bda
--- /dev/null
+++ b/libs/client/UserIdentity.cpp
@@ -0,0 +1,22 @@
+#include "UserIdentity.hpp"
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+cta::UserIdentity::UserIdentity() throw():
+  uid(0),
+  gid(0) {
+}
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+cta::UserIdentity::UserIdentity(
+  const uint32_t uid,
+  const uint32_t gid,
+  const std::string &host) throw():
+  uid(uid),
+  gid(gid),
+  host(host) {
+}
diff --git a/libs/client/UserIdentity.hpp b/libs/client/UserIdentity.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1b9d36ec15bd98789d72550f7b3b81884e8b03fa
--- /dev/null
+++ b/libs/client/UserIdentity.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <stdint.h>
+#include <string>
+
+namespace cta {
+
+/**
+ * Class reprsenting the identity of a user.
+ */
+struct UserIdentity {
+
+  /**
+   * The user ID of the user.
+   */
+  uint32_t uid;
+
+  /**
+   * The group ID of the user.
+   */
+  uint32_t gid;
+
+  /**
+   * The host from which the user is communicating.
+   */
+  std::string host;
+
+  /**
+   * Constructor.
+   *
+   * Initialises all integer member-variables to 0.
+   */
+  UserIdentity() throw();
+
+  /**
+   * Constructor.
+   *
+   * @param uid The user ID of the user.
+   * @param gid The group ID of the user.
+   * @param host The host from which the user is communicating.
+   */
+  UserIdentity(const uint32_t uid, const uint32_t gid, const std::string &host)
+    throw();
+
+}; // struct UserIdentity
+
+} // namespace cta
diff --git a/objectstore/RecallJob.hpp b/objectstore/RecallJob.hpp
index 5769b020d87cfda023667a2ee8a9ea76472f8c2f..bca006c2885914e5c13dad4419fbabb40fa8da8f 100644
--- a/objectstore/RecallJob.hpp
+++ b/objectstore/RecallJob.hpp
@@ -48,4 +48,4 @@ public:
   }
 };
  
-}}
\ No newline at end of file
+}}
diff --git a/unit_tests/CMakeLists.txt b/tests/CMakeLists.txt
similarity index 84%
rename from unit_tests/CMakeLists.txt
rename to tests/CMakeLists.txt
index 4cda2e4d98d9ea9b6a4c19ba36551043132efa79..d6d778a39420c5b2c7563dc0e8206399ddbc76ed 100644
--- a/unit_tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -5,7 +5,7 @@ include_directories(${PROJECT_SOURCE_DIR}/libs/ctacommon)
 include_directories(${PROJECT_SOURCE_DIR}/libs/ctaclient)
 
 add_executable(unittests
-  ${PROJECT_SOURCE_DIR}/libs/client/MockAPITest.cpp
+  ${PROJECT_SOURCE_DIR}/libs/client/MockClientAPITest.cpp
   unit_tests.cpp)
 
 target_link_libraries(unittests
diff --git a/unit_tests/unit_tests.cpp b/tests/unit_tests.cpp
similarity index 100%
rename from unit_tests/unit_tests.cpp
rename to tests/unit_tests.cpp
diff --git a/xroot_clients/CTACmd.cpp b/xroot_clients/CTACmd.cpp
index eb1e47d7f88fd8250197b380fc5feb65e956f22a..7d9611cb5f8fd3684ab44673acecc9c31a60c974 100644
--- a/xroot_clients/CTACmd.cpp
+++ b/xroot_clients/CTACmd.cpp
@@ -20,12 +20,13 @@ void CTACmd::usage(std::ostream &os) const throw() {
   os <<
     "Usage:\n"
     "\t" << m_programName << " archive <source_file1> [<source_file2> [<source_file3> [...]]] <destination_path>\n"
-    "\t" << m_programName << " create-storage-class <storage_class_name> <number_of_tape_copies>\n"
-    "\t" << m_programName << " change-storage-class <directory_name> <storage_class_name>\n"
-    "\t" << m_programName << " delete-storage-class <storage_class_name>\n"
-    "\t" << m_programName << " list-storage-class\n"
+    "\t" << m_programName << " mkclass <storage_class_name> <number_of_tape_copies>\n"
+    "\t" << m_programName << " chclass <directory_name> <storage_class_name>\n"
+    "\t" << m_programName << " rmclass <storage_class_name>\n"
+    "\t" << m_programName << " lsclass\n"
     "\t" << m_programName << " mkdir <directory_name>\n"
-    "\t" << m_programName << " rmdir <directory_name>\n";
+    "\t" << m_programName << " rmdir <directory_name>\n"
+    "\t" << m_programName << " ls <directory_name>\n";
 }
 
 //------------------------------------------------------------------------------
@@ -57,13 +58,14 @@ int CTACmd::executeCommand(const int argc, char **argv)  {
   XrdCl::FileSystem fs(XrdCl::URL("localhost"));
   std::string queryString = "/";
   queryString += argv[1];
-  queryString += "?";  
-  for(int i=2; i<argc-1; i++) {
-    queryString += argv[i];
-    queryString += "+";
-  }  
-  queryString += argv[argc-1];
-          
+  queryString += "?";
+  if(argc > 2) {  
+    for(int i=2; i<argc-1; i++) {
+      queryString += argv[i];
+      queryString += "+";
+    }  
+    queryString += argv[argc-1];
+  }        
   XrdCl::Buffer arg;
   arg.FromString(queryString.c_str());
   XrdCl::Buffer* response = 0;
diff --git a/xroot_plugins/CMakeLists.txt b/xroot_plugins/CMakeLists.txt
index c33b24a1f9c5d119e6ae3d8f0801d2c3a1969bf0..c68aefd0003dec650b499938fa7d8a8c1aa68085 100644
--- a/xroot_plugins/CMakeLists.txt
+++ b/xroot_plugins/CMakeLists.txt
@@ -5,3 +5,4 @@ find_package (xrootd REQUIRED)
 include_directories (${XROOTD_INCLUDE_DIR} ${XROOTD_PRIVATE_INCLUDE_DIR} ${CMAKE_SOURCE_DIR})
 
 add_library (XrdProFst MODULE XrdProFilesystem.cpp ParsedRequest.cpp)
+target_link_libraries (XrdProFst ctaclient)
\ No newline at end of file
diff --git a/xroot_plugins/XrdProFilesystem.cpp b/xroot_plugins/XrdProFilesystem.cpp
index 9453fc26eb82cd6a1032de546e7aea86a1099fd0..c183236aefb0649104dfba4c60fbced15518ea6c 100644
--- a/xroot_plugins/XrdProFilesystem.cpp
+++ b/xroot_plugins/XrdProFilesystem.cpp
@@ -3,6 +3,7 @@
 #include "XrdOuc/XrdOucString.hh"
 #include "XrdSec/XrdSecEntity.hh"
 #include "XrdVersion.hh"
+#include "libs/client/Exception.hpp"
 
 #include <iostream>
 #include <pwd.h>
@@ -99,82 +100,186 @@ int XrdProFilesystem::executeArchiveCommand(ParsedRequest &req, XrdOucErrInfo &e
     eInfo.setErrInfo(response.length(), response.c_str());
     return SFS_DATA;
   }
-  std::string response = "[OK] Requested archival of the following files:\n";
-  for(int i=0; i<req.args.size()-1; i++) {
+  try {
+    std::list<std::string> sourceFiles;
+    std::string destinationPath = req.args.at(req.args.size()-1);
+    for(int i=0; i<req.args.size()-1; i++) {
+      sourceFiles.push_back(req.args.at(i));
+    }
+    cta::UserIdentity requester;
+    std::string jobID = m_clientAPI->archiveToTape(requester, sourceFiles, destinationPath);
+    std::string response = "[OK] Requested archival of the following files:\n";
+    for(std::list<std::string>::iterator it = sourceFiles.begin(); it != sourceFiles.end(); it++) {
+      response += "[OK]\t";
+      response += *it;
+      response += "\n";
+    }
+    response += "[OK] To the following directory:\n";
     response += "[OK]\t";
-    response += req.args.at(i);
-    response += "\n";
-  }  
-  response += "[OK] To the following directory:\n";
-  response += "[OK]\t";
-  response += req.args.at(req.args.size()-1);
-  eInfo.setErrInfo(response.length(), response.c_str());
-  return SFS_DATA;
+    response += destinationPath;   
+    response += "\n[OK] JobID: ";
+    response += jobID;
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
 }
 
 //------------------------------------------------------------------------------
 // executeCreateStorageClassCommand
 //------------------------------------------------------------------------------
-int XrdProFilesystem::executeCreateStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
+int XrdProFilesystem::executeMkclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
   if(req.args.size() != 2) {
     std::string response = "[ERROR] Wrong number of arguments provided";
     eInfo.setErrInfo(response.length(), response.c_str());
     return SFS_DATA;
   }
-  std::string response = "[OK] Created storage class ";
-  response += req.args.at(0);
-  response += " with ";
-  response += req.args.at(1);
-  response += " tape copies";
-  eInfo.setErrInfo(response.length(), response.c_str());
-  return SFS_DATA;
+  try {
+    uint8_t numberOfCopies;
+    std::istringstream ss(req.args.at(1));
+    ss >> numberOfCopies;
+    cta::UserIdentity requester;
+    m_clientAPI->createStorageClass(requester, req.args.at(0), numberOfCopies);
+    std::string response = "[OK] Created storage class ";
+    response += req.args.at(0);
+    response += " with ";
+    response += req.args.at(1);
+    response += " tape copies";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
 }
 
 //------------------------------------------------------------------------------
 // executeCreateStorageClassCommand
 //------------------------------------------------------------------------------
-int XrdProFilesystem::executeChangeStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
+int XrdProFilesystem::executeChclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
   if(req.args.size() != 2) {
     std::string response = "[ERROR] Wrong number of arguments provided";
     eInfo.setErrInfo(response.length(), response.c_str());
     return SFS_DATA;
   }
-  std::string response = "[OK] Changed storage class of directory ";
-  response += req.args.at(0);
-  response += " to ";
-  response += req.args.at(1);
-  eInfo.setErrInfo(response.length(), response.c_str());
-  return SFS_DATA;
+  try {
+    std::string response = "[OK] Changed storage class of directory ";
+    response += req.args.at(0);
+    response += " to ";
+    response += req.args.at(1);
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
 }
 
 //------------------------------------------------------------------------------
 // executeDeleteStorageClassCommand
 //------------------------------------------------------------------------------
-int XrdProFilesystem::executeDeleteStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
+int XrdProFilesystem::executeRmclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
   if(req.args.size() != 1) {
     std::string response = "[ERROR] Wrong number of arguments provided";
     eInfo.setErrInfo(response.length(), response.c_str());
     return SFS_DATA;
   }
-  std::string response = "[OK] Storage class ";
-  response += req.args.at(0);
-  response += " deleted";
-  eInfo.setErrInfo(response.length(), response.c_str());
-  return SFS_DATA;
+  try {
+    cta::UserIdentity requester;
+    m_clientAPI->deleteStorageClass(requester, req.args.at(0));
+    std::string response = "[OK] Storage class ";
+    response += req.args.at(0);
+    response += " deleted";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
 }
 
 //------------------------------------------------------------------------------
 // executeListStorageClassCommand
 //------------------------------------------------------------------------------
-int XrdProFilesystem::executeListStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
+int XrdProFilesystem::executeLsclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
   if(req.args.size() != 0) {
     std::string response = "[ERROR] Wrong number of arguments provided";
     eInfo.setErrInfo(response.length(), response.c_str());
     return SFS_DATA;
   }
-  std::string response = "[OK] Requested listing of the storage classes";
-  eInfo.setErrInfo(response.length(), response.c_str());
-  return SFS_DATA;
+  try {
+    cta::UserIdentity requester;
+    std::list<cta::StorageClass> stgList = m_clientAPI->getStorageClasses(requester);
+    std::string response = "[OK] Listing of the storage class names and no of copies:";
+    for(std::list<cta::StorageClass>::iterator it = stgList.begin(); it != stgList.end(); it++) {
+      response += "\n";
+      response += it->name;
+      response += " ";
+      response += it->nbCopies;
+    }
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
 }
 
 //------------------------------------------------------------------------------
@@ -186,11 +291,29 @@ int XrdProFilesystem::executeMkdirCommand(ParsedRequest &req, XrdOucErrInfo &eIn
     eInfo.setErrInfo(response.length(), response.c_str());
     return SFS_DATA;
   }
-  std::string response = "[OK] Directory ";
-  response += req.args.at(0);
-  response += " created";
-  eInfo.setErrInfo(response.length(), response.c_str());
-  return SFS_DATA;
+  try {
+    cta::UserIdentity requester;
+    m_clientAPI->createDirectory(requester, req.args.at(0));
+    std::string response = "[OK] Directory ";
+    response += req.args.at(0);
+    response += " created";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
 }
 
 //------------------------------------------------------------------------------
@@ -202,11 +325,84 @@ int XrdProFilesystem::executeRmdirCommand(ParsedRequest &req, XrdOucErrInfo &eIn
     eInfo.setErrInfo(response.length(), response.c_str());
     return SFS_DATA;
   }
-  std::string response = "[OK] Directory ";
-  response += req.args.at(0);
-  response += " removed";
-  eInfo.setErrInfo(response.length(), response.c_str());
-  return SFS_DATA;
+  try {
+    std::string response = "[OK] Directory ";
+    response += req.args.at(0);
+    response += " removed";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
+}
+
+//------------------------------------------------------------------------------
+// executeLsCommand
+//------------------------------------------------------------------------------
+int XrdProFilesystem::executeLsCommand(ParsedRequest &req, XrdOucErrInfo &eInfo) {
+  if(req.args.size() != 1) {
+    std::string response = "[ERROR] Wrong number of arguments provided";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
+  try {
+    cta::UserIdentity requester;
+    std::string response;
+    cta::DirectoryIterator itor = m_clientAPI->getDirectoryContents(requester, req.args.at(0));
+    while(itor.hasMore()) {
+      const cta::DirectoryEntry &entry = itor.next();
+      response += "\n";
+      switch(entry.entryType) {
+        case cta::DirectoryEntry::FILE_ENTRY:
+          response += "-";
+          break;
+        case cta::DirectoryEntry::DIRECTORY_ENTRY:
+          response += "d";
+          break;
+        case cta::DirectoryEntry::NONE:
+        default:          
+          response += "n";
+          break;
+      }
+      response += entry.ownerPerms;
+      response += entry.groupPerms;
+      response += entry.otherPerms;
+      response += " ";
+      response += entry.ownerId;
+      response += " ";
+      response += entry.groupId;
+      response += " ";
+      response += entry.name;
+    }
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (cta::Exception &ex) {
+    std::string response = "[ERROR] CTA exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (std::exception &ex) {
+    std::string response = "[ERROR] Exception caught: ";
+    response += ex.what();
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  } catch (...) {
+    std::string response = "[ERROR] Unknown exception caught!";
+    eInfo.setErrInfo(response.length(), response.c_str());
+    return SFS_DATA;
+  }
 }
 
 //------------------------------------------------------------------------------
@@ -222,21 +418,21 @@ int XrdProFilesystem::dispatchRequest(XrdSfsFSctl &args, XrdOucErrInfo &eInfo) {
   {  
     return executeArchiveCommand(req, eInfo);
   }
-  else if(strcmp(req.cmd.c_str(), "/create-storage-class") == 0)
+  else if(strcmp(req.cmd.c_str(), "/mkclass") == 0)
   {  
-    return executeCreateStorageClassCommand(req, eInfo);
+    return executeMkclassCommand(req, eInfo);
   }  
-  else if(strcmp(req.cmd.c_str(), "/change-storage-class") == 0)
+  else if(strcmp(req.cmd.c_str(), "/chclass") == 0)
   {  
-    return executeChangeStorageClassCommand(req, eInfo);
+    return executeChclassCommand(req, eInfo);
   }
-  else if(strcmp(req.cmd.c_str(), "/delete-storage-class") == 0)
+  else if(strcmp(req.cmd.c_str(), "/rmclass") == 0)
   {  
-    return executeDeleteStorageClassCommand(req, eInfo);
+    return executeRmclassCommand(req, eInfo);
   }
-  else if(strcmp(req.cmd.c_str(), "/list-storage-class") == 0)
+  else if(strcmp(req.cmd.c_str(), "/lsclass") == 0)
   {  
-    return executeListStorageClassCommand(req, eInfo);
+    return executeLsclassCommand(req, eInfo);
   }
   else if(strcmp(req.cmd.c_str(), "/mkdir") == 0)
   {  
@@ -245,6 +441,10 @@ int XrdProFilesystem::dispatchRequest(XrdSfsFSctl &args, XrdOucErrInfo &eInfo) {
   else if(strcmp(req.cmd.c_str(), "/rmdir") == 0)
   {  
     return executeRmdirCommand(req, eInfo);
+  }  
+  else if(strcmp(req.cmd.c_str(), "/ls") == 0)
+  {  
+    return executeLsCommand(req, eInfo);
   }
   else
   {
@@ -449,9 +649,13 @@ void XrdProFilesystem::EnvInfo(XrdOucEnv *envP)
 //------------------------------------------------------------------------------
 // constructor
 //------------------------------------------------------------------------------
-XrdProFilesystem::XrdProFilesystem() {}
+XrdProFilesystem::XrdProFilesystem() {
+  m_clientAPI = new cta::MockClientAPI();
+}
 
 //------------------------------------------------------------------------------
 // destructor
 //------------------------------------------------------------------------------
-XrdProFilesystem::~XrdProFilesystem() {}
\ No newline at end of file
+XrdProFilesystem::~XrdProFilesystem() {
+  delete m_clientAPI;
+}
diff --git a/xroot_plugins/XrdProFilesystem.hpp b/xroot_plugins/XrdProFilesystem.hpp
index d679c3e9327d99a5187c11bfd46f5a9a36979d1e..b45287319aebbf8563da6ffe9890762ca018604d 100644
--- a/xroot_plugins/XrdProFilesystem.hpp
+++ b/xroot_plugins/XrdProFilesystem.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "libs/client/MockClientAPI.hpp"
 #include "XrdSfs/XrdSfsInterface.hh"
 
 #include "ParsedRequest.hpp"
@@ -29,6 +30,11 @@ public:
   ~XrdProFilesystem();
   
 protected:
+  
+  /**
+   * Pointer to the client API object
+   */
+  cta::ClientAPI *m_clientAPI;
     
   /**
    * Parses the query into the request structure
@@ -65,7 +71,7 @@ protected:
    * @param eInfo   Error information
    * @return SFS_DATA
    */
-  int executeCreateStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
+  int executeMkclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
   
   /**
    * Executes the command contained within the request structure
@@ -74,7 +80,7 @@ protected:
    * @param eInfo   Error information
    * @return SFS_DATA
    */
-  int executeChangeStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
+  int executeChclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
   
   /**
    * Executes the command contained within the request structure
@@ -83,7 +89,7 @@ protected:
    * @param eInfo   Error information
    * @return SFS_DATA
    */
-  int executeDeleteStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
+  int executeRmclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
   
   /**
    * Executes the command contained within the request structure
@@ -92,7 +98,7 @@ protected:
    * @param eInfo   Error information
    * @return SFS_DATA
    */
-  int executeListStorageClassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
+  int executeLsclassCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
   
   /**
    * Executes the command contained within the request structure
@@ -112,6 +118,15 @@ protected:
    */
   int executeRmdirCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
   
+  /**
+   * Executes the command contained within the request structure
+   * 
+   * @param req     parsed request
+   * @param eInfo   Error information
+   * @return SFS_DATA
+   */
+  int executeLsCommand(ParsedRequest &req, XrdOucErrInfo &eInfo);
+  
   /**
    * Dispatches the request based on the query
    *