protected Node fromRepository(
      CmrRepository repository, ArtifactContext context, boolean addLeaf) {
    log.debug(" Trying repository " + repository.getDisplayString());
    Node node = repository.findParent(context);
    if (node != null) {
      if (addLeaf) {
        Node parent = node;
        context.toNode(parent);
        NodeUtils.keepRepository(parent, repository);
        try {
          String[] names = repository.getArtifactNames(context);
          for (String name : names) {
            node = parent.getChild(name);
            if (node != null) {
              break;
            }
          }
        } finally {
          ArtifactContext.removeNode(parent);
        }
      }

      if (node != null) {
        NodeUtils.keepRepository(node, repository);
        log.debug("  -> Found at " + NodeUtils.getFullPath(node));
      }
    }
    return node;
  }
 public void putArtifact(ArtifactContext context, InputStream content) throws RepositoryException {
   try {
     final Node parent = getOrCreateParent(context);
     log.debug("Adding artifact " + context + " to cache " + cache.getDisplayString());
     log.debug(" -> " + NodeUtils.getFullPath(parent));
     final String[] names = cache.getArtifactNames(context);
     if (names.length != 1) {
       throw new RepositoryException("ArtifactContext should have a single suffix");
     }
     final String label = names[0];
     try {
       if (parent instanceof OpenNode) {
         final OpenNode on = (OpenNode) parent;
         if (on.addContent(label, content, context) == null)
           addContent(context, parent, label, content);
       } else {
         addContent(context, parent, label, content);
       }
     } catch (IOException e) {
       throw new RepositoryException(e);
     }
     log.debug(" -> [done]");
   } finally {
     IOUtils.safeClose(content);
   }
 }
  @Override
  protected void putFolder(ArtifactContext context, File folder) throws RepositoryException {
    Node parent = getOrCreateParent(context);
    log.debug("Adding folder " + context + " to cache " + cache.getDisplayString());
    log.debug(" -> " + NodeUtils.getFullPath(parent));

    // fast-path for Herd
    if (!canHandleFolders()) {
      uploadZipped(parent, context, folder);
      return;
    }

    final String[] names = cache.getArtifactNames(context);
    if (names.length != 1) {
      throw new RepositoryException("ArtifactContext should have a single suffix");
    }
    final String label = names[0];
    if (parent instanceof OpenNode) {
      final OpenNode on = (OpenNode) parent;
      final OpenNode curent = on.createNode(label);
      try {
        for (File f : folder.listFiles()) // ignore folder, it should match new root
        putFiles(curent, f, context);
      } catch (RepositoryException e) {
        throw e;
      } catch (Exception e) {
        removeArtifact(context);
        throw new RepositoryException(e);
      }
    } else {
      throw new RepositoryException(
          "Cannot put folder [" + folder + "] to non-open node: " + context);
    }
    log.debug(" -> [done]");
  }
 public List<String> getRepositoriesDisplayString() {
   final List<String> displayStrings = new ArrayList<>();
   for (CmrRepository root : getRepositories()) {
     displayStrings.add(root.getDisplayString());
   }
   return displayStrings;
 }
 public void removeArtifact(ArtifactContext context) throws RepositoryException {
   Node parent = getFromCacheNode(context, false);
   log.debug("Remove artifact " + context + " to repository " + cache.getDisplayString());
   if (parent != null) {
     final String[] labels = cache.getArtifactNames(context);
     for (String label : labels) {
       try {
         removeNode(parent, label);
       } catch (IOException e) {
         throw new RepositoryException(e);
       }
     }
     log.debug(" -> [done]");
   } else {
     log.debug(" -> No such artifact: " + context);
   }
 }