security: Make public interface of Pib, Identity, and Key as read-only

Change-Id: I7b3fac583c00cce2fa09802fa4d0aff2ace4aca2
Refs: #2928
diff --git a/src/security/identity.cpp b/src/security/identity.cpp
index 7662a0a..128b7bc 100644
--- a/src/security/identity.cpp
+++ b/src/security/identity.cpp
@@ -90,7 +90,7 @@
 }
 
 Key
-Identity::getKey(const name::Component& keyId)
+Identity::getKey(const name::Component& keyId) const
 {
   validityCheck();
 
@@ -98,7 +98,7 @@
 }
 
 const KeyContainer&
-Identity::getKeys()
+Identity::getKeys() const
 {
   validityCheck();
 
@@ -130,7 +130,7 @@
 }
 
 Key&
-Identity::getDefaultKey()
+Identity::getDefaultKey() const
 {
   validityCheck();
 
diff --git a/src/security/identity.hpp b/src/security/identity.hpp
index ecc42eb..533bfc9 100644
--- a/src/security/identity.hpp
+++ b/src/security/identity.hpp
@@ -46,6 +46,7 @@
 public:
   friend class Pib;
   friend class IdentityContainer;
+  friend class KeyChain;
 
 public:
   /**
@@ -73,6 +74,36 @@
   getName() const;
 
   /**
+   * @brief Get a key with id @keyId.
+   *
+   * @param identityName The name for the identity to get.
+   * @throw Pib::Error if the identity does not exist.
+   */
+  Key
+  getKey(const name::Component& keyId) const;
+
+  /// @brief Get all the keys for this Identity.
+  const KeyContainer&
+  getKeys() const;
+
+  /**
+   * @brief Get the default key for this Identity.
+   *
+   * @throws Pib::Error if the default key does not exist.
+   */
+  Key&
+  getDefaultKey() const;
+
+  /// @brief Check if the Identity instance is valid
+  operator bool() const;
+
+  /// @brief Check if the Identity instance is invalid
+  bool
+  operator!() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
+
+  /**
    * @brief Add a key.
    *
    * If the key already exists, do nothing.
@@ -96,19 +127,6 @@
   removeKey(const name::Component& keyId);
 
   /**
-   * @brief Get a key with id @keyId.
-   *
-   * @param identityName The name for the identity to get.
-   * @throw Pib::Error if the identity does not exist.
-   */
-  Key
-  getKey(const name::Component& keyId);
-
-  /// @brief Get all the keys for this Identity.
-  const KeyContainer&
-  getKeys();
-
-  /**
    * @brief Set the key with id @p keyId as the default key.
    *
    * @param keyId The key id component of the default key.
@@ -131,21 +149,6 @@
   Key&
   setDefaultKey(const PublicKey& publicKey, const name::Component& keyId = EMPTY_KEY_ID);
 
-  /**
-   * @brief Get the default key for this Identity.
-   *
-   * @throws Pib::Error if the default key does not exist.
-   */
-  Key&
-  getDefaultKey();
-
-  /// @brief Check if the Identity instance is valid
-  operator bool() const;
-
-  /// @brief Check if the Identity instance is invalid
-  bool
-  operator!() const;
-
 NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   /**
    * @brief Create an Identity with @p identityName.
@@ -176,11 +179,11 @@
 private:
   Name m_name;
 
-  bool m_hasDefaultKey;
-  Key m_defaultKey;
+  mutable bool m_hasDefaultKey;
+  mutable Key m_defaultKey;
 
-  bool m_needRefreshKeys;
-  KeyContainer m_keys;
+  mutable bool m_needRefreshKeys;
+  mutable KeyContainer m_keys;
 
   shared_ptr<PibImpl> m_impl;
 };
diff --git a/src/security/key.cpp b/src/security/key.cpp
index d7a1a6f..dc430c7 100644
--- a/src/security/key.cpp
+++ b/src/security/key.cpp
@@ -127,15 +127,15 @@
 }
 
 IdentityCertificate
-Key::getCertificate(const Name& certName)
+Key::getCertificate(const Name& certName) const
 {
   validityCheck();
 
   return m_impl->getCertificate(certName);
 }
 
-CertificateContainer
-Key::getCertificates()
+const CertificateContainer&
+Key::getCertificates() const
 {
   validityCheck();
 
@@ -167,7 +167,7 @@
 }
 
 const IdentityCertificate&
-Key::getDefaultCertificate()
+Key::getDefaultCertificate() const
 {
   validityCheck();
 
diff --git a/src/security/key.hpp b/src/security/key.hpp
index b3e4f96..31d7fe7 100644
--- a/src/security/key.hpp
+++ b/src/security/key.hpp
@@ -47,6 +47,7 @@
 public:
   friend class Identity;
   friend class KeyContainer;
+  friend class KeyChain;
 
 public:
   /**
@@ -86,6 +87,36 @@
   getPublicKey() const;
 
   /**
+   * @brief Get a certificate.
+   *
+   * @return the certificate
+   * @throws Pib::Error if the certificate does not exist.
+   */
+  IdentityCertificate
+  getCertificate(const Name& certName) const;
+
+  /// @brief Get all the certificates for this key.
+  const CertificateContainer&
+  getCertificates() const;
+
+  /**
+   * @brief Get the default certificate for this Key.
+   *
+   * @throws Pib::Error if the default certificate does not exist.
+   */
+  const IdentityCertificate&
+  getDefaultCertificate() const;
+
+  /// @brief Check if the Key instance is valid
+  operator bool() const;
+
+  /// @brief Check if the Key instance is invalid
+  bool
+  operator!() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
+
+  /**
    * @brief Add a certificate.
    *
    * @param certificate The certificate to add.
@@ -102,19 +133,6 @@
   removeCertificate(const Name& certName);
 
   /**
-   * @brief Get a certificate.
-   *
-   * @return the certificate
-   * @throws Pib::Error if the certificate does not exist.
-   */
-  IdentityCertificate
-  getCertificate(const Name& certName);
-
-  /// @brief Get all the certificates for this key.
-  CertificateContainer
-  getCertificates();
-
-  /**
    * @brief Set the default certificate.
    *
    * @param certName The name of the default certificate of the key.
@@ -136,21 +154,6 @@
   const IdentityCertificate&
   setDefaultCertificate(const IdentityCertificate& certificate);
 
-  /**
-   * @brief Get the default certificate for this Key.
-   *
-   * @throws Pib::Error if the default certificate does not exist.
-   */
-  const IdentityCertificate&
-  getDefaultCertificate();
-
-  /// @brief Check if the Key instance is valid
-  operator bool() const;
-
-  /// @brief Check if the Key instance is invalid
-  bool
-  operator!() const;
-
 NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   /**
    * @brief Create a Key with @p identityName and @p keyId.
@@ -189,11 +192,11 @@
   Name m_keyName;
   PublicKey m_key;
 
-  bool m_hasDefaultCertificate;
-  IdentityCertificate m_defaultCertificate;
+  mutable bool m_hasDefaultCertificate;
+  mutable IdentityCertificate m_defaultCertificate;
 
-  bool m_needRefreshCerts;
-  CertificateContainer m_certificates;
+  mutable bool m_needRefreshCerts;
+  mutable CertificateContainer m_certificates;
 
   shared_ptr<PibImpl> m_impl;
 };
diff --git a/src/security/pib.cpp b/src/security/pib.cpp
index 28ca508..fd392f6 100644
--- a/src/security/pib.cpp
+++ b/src/security/pib.cpp
@@ -28,6 +28,8 @@
 Pib::Pib(const std::string scheme, const std::string& location, shared_ptr<PibImpl> impl)
   : m_scheme(scheme)
   , m_location(location)
+  , m_hasDefaultIdentity(false)
+  , m_needRefreshIdentities(true)
   , m_impl(impl)
 {
 }
@@ -57,38 +59,60 @@
 Identity
 Pib::addIdentity(const Name& identity)
 {
+  if (!m_needRefreshIdentities && m_identities.find(identity) == m_identities.end()) {
+    // if we have already loaded all the identities, but the new identity is not one of them
+    // the IdentityContainer should be refreshed
+    m_needRefreshIdentities = true;
+  }
   return Identity(identity, m_impl, true);
 }
 
 void
 Pib::removeIdentity(const Name& identity)
 {
+  if (m_hasDefaultIdentity && m_defaultIdentity.getName() == identity)
+    m_hasDefaultIdentity = false;
+
   m_impl->removeIdentity(identity);
+  m_needRefreshIdentities = true;
 }
 
 Identity
-Pib::getIdentity(const Name& identity)
+Pib::getIdentity(const Name& identity) const
 {
   return Identity(identity, m_impl, false);
 }
 
-IdentityContainer
+const IdentityContainer&
 Pib::getIdentities() const
 {
-  return IdentityContainer(m_impl->getIdentities(), m_impl);
+  if (m_needRefreshIdentities) {
+    m_identities = std::move(IdentityContainer(m_impl->getIdentities(), m_impl));
+    m_needRefreshIdentities = false;
+  }
+
+  return m_identities;
 }
 
-Identity
+Identity&
 Pib::setDefaultIdentity(const Name& identityName)
 {
+  m_defaultIdentity = addIdentity(identityName);
+  m_hasDefaultIdentity = true;
+
   m_impl->setDefaultIdentity(identityName);
-  return Identity(identityName, m_impl, true);
+  return m_defaultIdentity;
 }
 
-Identity
-Pib::getDefaultIdentity()
+Identity&
+Pib::getDefaultIdentity() const
 {
-  return Identity(m_impl->getDefaultIdentity(), m_impl, false);
+  if (!m_hasDefaultIdentity) {
+    m_defaultIdentity = std::move(Identity(m_impl->getDefaultIdentity(), m_impl, false));
+    m_hasDefaultIdentity = true;
+  }
+
+  return m_defaultIdentity;
 }
 
 
diff --git a/src/security/pib.hpp b/src/security/pib.hpp
index b307c83..5d28edd 100644
--- a/src/security/pib.hpp
+++ b/src/security/pib.hpp
@@ -98,6 +98,30 @@
   std::string
   getTpmLocator() const;
 
+  /**
+   * @brief Get an identity with name @p identityName.
+   *
+   * @param identityName The name for the identity to get.
+   * @throw Pib::Error if the identity does not exist.
+   */
+  Identity
+  getIdentity(const Name& identityName) const;
+
+  /// @brief Get all the identities
+  const IdentityContainer&
+  getIdentities() const;
+
+  /**
+   * @brief Get the default identity.
+   *
+   * @return the default identity.
+   * @throws Pib::Error if no default identity.
+   */
+  Identity&
+  getDefaultIdentity() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
+
   /*
    * @brief Create an identity with name @p identityName and return a reference to it.
    *
@@ -118,19 +142,6 @@
   removeIdentity(const Name& identityName);
 
   /**
-   * @brief Get an identity with name @p identityName.
-   *
-   * @param identityName The name for the identity to get.
-   * @throw Pib::Error if the identity does not exist.
-   */
-  Identity
-  getIdentity(const Name& identityName);
-
-  /// @brief Get all the identities
-  IdentityContainer
-  getIdentities() const;
-
-  /**
    * @brief Set an identity with name @p identityName as the default identity.
    *
    * Also create the identity if it does not exist.
@@ -138,18 +149,9 @@
    * @param identityName The name for the default identity.
    * @return the default identity
    */
-  Identity
+  Identity&
   setDefaultIdentity(const Name& identityName);
 
-  /**
-   * @brief Get the default identity.
-   *
-   * @return the default identity.
-   * @throws Pib::Error if no default identity.
-   */
-  Identity
-  getDefaultIdentity();
-
 NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   /*
    * @brief Create a new Pib with the specified @p location
@@ -169,6 +171,13 @@
 protected:
   std::string m_scheme;
   std::string m_location;
+
+  mutable bool m_hasDefaultIdentity;
+  mutable Identity m_defaultIdentity;
+
+  mutable bool m_needRefreshIdentities;
+  mutable IdentityContainer m_identities;
+
   shared_ptr<PibImpl> m_impl;
 };