/**
   * This function returns a RepositoryNode with a canonicalized path.
   *
   * @param url the url in String form
   * @param create true iff the node should be created if absent
   * @return RepositoryNode the node
   * @throws MalformedURLException
   */
  private synchronized RepositoryNode getNode(String url, boolean create)
      throws MalformedURLException {
    String canonUrl;
    boolean isAuUrl = false;
    if (AuUrl.isAuUrl(url)) {
      // path information is lost here, but is unimportant if it's an AuUrl
      canonUrl = AuUrl.PROTOCOL;
      isAuUrl = true;
    } else {
      // create a canonical path, handling all illegal path traversal
      canonUrl = canonicalizePath(url);
    }

    // check LRUMap cache for node
    RepositoryNode node = (RepositoryNode) nodeCache.get(nodeCacheKey(canonUrl));
    if (node != null) {
      return node;
    }

    String nodeLocation;
    if (isAuUrl) {
      // base directory of ArchivalUnit
      nodeLocation = rootLocation;
      node = new AuNodeImpl(canonUrl, nodeLocation, this);
    } else {
      // determine proper node location
      nodeLocation =
          LockssRepositoryImpl.mapUrlToFileLocation(rootLocation, canonUrl)
              .replace("?", "")
              .replace("COM8", "COMEIGHT")
              .replace("%5c", "/"); // //windows folder structure fix
      node = new RepositoryNodeImpl(canonUrl, nodeLocation, this);
    }

    if (!create) {
      // if not creating, check for existence
      File nodeDir = new File(nodeLocation);
      if (!nodeDir.exists()) {
        // return null if the node doesn't exist and shouldn't be created
        return null;
      }
      if (!nodeDir.isDirectory()) {
        logger.error("Cache file not a directory: " + nodeLocation);
        throw new LockssRepository.RepositoryStateException("Invalid cache file.");
      }
    }

    // add to node cache
    nodeCache.put(nodeCacheKey(canonUrl), node);
    return node;
  }
 int getRefMisses() {
   return nodeCache.getRefMisses();
 }
 int getRefHits() {
   return nodeCache.getRefHits();
 }
 int getCacheMisses() {
   return nodeCache.getCacheMisses();
 }
 // functions for testing
 int getCacheHits() {
   return nodeCache.getCacheHits();
 }
 public void setNodeCacheSize(int size) {
   if (nodeCache != null && !isGlobalNodeCache && nodeCache.getMaxSize() != size) {
     nodeCache.setMaxSize(size);
   }
 }