/**
  * Get the version of the stored node key name
  *
  * @return the version
  */
 public NDNTime nodeKeyVersion() {
   try {
     return VersioningProfile.getLastVersionAsTimestamp(storedNodeKeyName());
   } catch (VersionMissingException e) {
     if (Log.isLoggable(Log.FAC_ACCESSCONTROL, Level.WARNING)) {
       Log.warning(
           Log.FAC_ACCESSCONTROL,
           "Unexpected: name that was confirmed to have a version on construction throws a VersionMissingException: "
               + storedNodeKeyName());
     }
     throw new IllegalStateException(
         "Unexpected: name that was confirmed to have a version on construction throws a VersionMissingException: "
             + storedNodeKeyName());
   }
 }
 /**
  * Computes the descendant node key for a specified descendant node using the key derivation
  * function.
  *
  * @param descendantNodeName the name of the descendant node
  * @param keyLabel the label of the key
  * @return the node key
  * @throws InvalidKeyException
  * @throws ContentEncodingException
  */
 public NodeKey computeDescendantNodeKey(ContentName descendantNodeName, String keyLabel)
     throws InvalidKeyException, ContentEncodingException {
   if (nodeName().equals(descendantNodeName)) {
     if (Log.isLoggable(Log.FAC_ACCESSCONTROL, Level.INFO)) {
       Log.info(
           Log.FAC_ACCESSCONTROL,
           "Asked to compute ourselves as our own descendant (node key "
               + nodeName()
               + "), returning this.");
     }
     return this;
   }
   if (!nodeName().isPrefixOf(descendantNodeName)) {
     throw new IllegalArgumentException(
         "Node " + descendantNodeName + " is not a child of this node " + nodeName());
   }
   byte[] derivedKey =
       KeyDerivationFunction.DeriveKeyForNode(
           nodeName(), nodeKey().getEncoded(), keyLabel, descendantNodeName);
   return new NodeKey(descendantNodeName, derivedKey, storedNodeKeyName(), storedNodeKeyID());
 }
  /**
   * Read policy from persistent storage under standard naming convention. This method may be called
   * optionally during initialization by a subclass after it is initialized enough to process
   * getContent() calls
   *
   * @param globalPrefix - used to find our policy file
   * @return XML for the current policy or null if no current policy
   * @throws MalformedContentNameStringException
   * @throws IOException
   */
  public PolicyXML readPolicy(ContentName globalPrefix)
      throws MalformedContentNameStringException, IOException {
    if (Log.isLoggable(Log.FAC_REPO, Level.INFO))
      Log.info(
          Log.FAC_REPO,
          "REPO: reading policy from network: {0}/{1}/{2}",
          REPO_NAMESPACE,
          globalPrefix,
          REPO_POLICY);
    ContentName policyName = BasicPolicy.getPolicyName(globalPrefix);

    // We can't use the regular repo handle for this because we need ndnd to communicate across the
    // faces
    NDNHandle readHandle;
    readHandle = NDNHandle.open(_km);
    PolicyObject policyObject = new PolicyObject(policyName, readHandle);
    try {
      return policyObject.policyInfo();
    } catch (ContentNotReadyException cge) {
    } finally {
      readHandle.close();
    }
    return null;
  }