@Override
 public void shredItem(
     final Repository repository,
     final File repositoryBaseDir,
     final ResourceStoreRequest request,
     final File target)
     throws ItemNotFoundException, UnsupportedStorageOperationException, LocalStorageException {
   if (getLogger().isDebugEnabled()) {
     getLogger().debug("Deleting file: " + target.getAbsolutePath());
   }
   if (target.isDirectory()) {
     try {
       FileUtils.deleteDirectory(target);
     } catch (IOException ex) {
       throw new LocalStorageException(
           String.format(
               "Could not delete directory in repository %s from path \"%s\"",
               RepositoryStringUtils.getHumanizedNameString(repository), target.getAbsolutePath()),
           ex);
     }
   } else if (target.isFile()) {
     try {
       FileUtils.forceDelete(target);
     } catch (IOException ex) {
       throw new LocalStorageException(
           String.format(
               "Could not delete file in repository %s from path \"%s\"",
               RepositoryStringUtils.getHumanizedNameString(repository),
               target.getAbsolutePath()));
     }
   } else {
     throw new ItemNotFoundException(request, repository);
   }
 }
  protected void gatherArtifactNodeInfoIfAvailable(
      final String path, final DefaultMergedTreeNode mnode) {
    if (!CHECK_LOCAL_AVAILABILITY) {
      return;
    }

    final ResourceStoreRequest request = getResourceStoreRequest(path);
    // default it to not available
    mnode.setLocallyAvailable(false);
    try {
      final StorageItem item = getRepository().retrieveItem(request);
      if (item instanceof StorageFileItem) {
        mnode.setLocallyAvailable(true);
        mnode.setArtifactTimestamp(item.getModified());
        mnode.setArtifactMd5Checksum(
            item.getRepositoryItemAttributes().get(DigestCalculatingInspector.DIGEST_MD5_KEY));
        mnode.setArtifactSha1Checksum(
            item.getRepositoryItemAttributes().get(DigestCalculatingInspector.DIGEST_SHA1_KEY));
        mnode.setInitiatorUserId(
            item.getRepositoryItemAttributes().get(AccessManager.REQUEST_USER));
        mnode.setInitiatorIpAddress(
            item.getRepositoryItemAttributes().get(AccessManager.REQUEST_REMOTE_ADDRESS));
        mnode.setArtifactOriginUrl(item.getRemoteUrl());
        if (!StringUtils.isEmpty(mnode.getArtifactOriginUrl())) {
          mnode.setArtifactOriginReason("cached");
        } else {
          mnode.setArtifactOriginReason("deployed");
        }
      }
    } catch (ItemNotFoundException e) {
      // mute it, probably not available locally
    } catch (AccessDeniedException e) {
      // mute it, probably user does not have authz to access this part of repo
    } catch (IllegalOperationException e) {
      // like "repo is out of service", but why is then tree view accessed at all? In that case it's
      // a bug
      logger.warn(
          "Illegal operation tried against repository {}",
          RepositoryStringUtils.getHumanizedNameString(getRepository()),
          e);
    } catch (StorageException e) {
      // this is lethal, some "io related" problem. Is basically IOException and is a problem on
      // your instance or HW/net
      logger.warn(
          "IO related problem in repository {}",
          RepositoryStringUtils.getHumanizedNameString(getRepository()),
          e);
    }
  }
 protected void mkDirs(final Repository repository, final File target)
     throws LocalStorageException {
   if (!target.exists() && !target.mkdirs()) {
     // re-check is it really a "good" parent?
     if (!target.isDirectory()) {
       throw new LocalStorageException(
           String.format(
               "Could not create the directory hiearchy in repository %s to write \"%s\"",
               RepositoryStringUtils.getHumanizedNameString(repository),
               target.getAbsolutePath()));
     }
   }
 }
 /**
  * Beside original behavior, only add to NFC when remote access is not rejected by autorouting.
  *
  * @since 2.4
  */
 @Override
 protected boolean shouldAddToNotFoundCache(final ResourceStoreRequest request) {
   boolean shouldAddToNFC = super.shouldAddToNotFoundCache(request);
   if (shouldAddToNFC
       && request.getRequestContext().containsKey(Manager.ROUTING_REQUEST_REJECTED_FLAG_KEY)) {
     // TODO: should we un-flag the request?
     shouldAddToNFC = false;
     getLogger()
         .debug(
             "Maven proxy repository {} autorouting rejected this request, not adding path {} to NFC.",
             RepositoryStringUtils.getHumanizedNameString(this),
             request.getRequestPath());
   }
   return shouldAddToNFC;
 }
 protected boolean isPathAvailable(String path) {
   if (!CHECK_LOCAL_AVAILABILITY) {
     return false;
   }
   try {
     final ResourceStoreRequest request = getResourceStoreRequest(path);
     return getRepository().getLocalStorage().containsItem(getRepository(), request);
   } catch (Exception e) {
     // for whatever reason, couldn't see item, so it's not cached locally we shall say
     logger.warn(
         "IO related problem during local storage availability check in repository {}",
         RepositoryStringUtils.getHumanizedNameString(getRepository()),
         e);
   }
   return false;
 }
  @Override
  public Collection<File> listItems(
      final Repository repository,
      final File repositoryBaseDir,
      final ResourceStoreRequest request,
      final File target)
      throws ItemNotFoundException, LocalStorageException {
    if (target.isDirectory()) {
      List<File> result = new ArrayList<File>();

      File[] files =
          target.listFiles(
              new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                  return !pathname.getName().endsWith(HIDDEN_TARGET_SUFFIX);
                }
              });

      if (files != null) {
        for (int i = 0; i < files.length; i++) {
          if (files[i].isFile() || files[i].isDirectory()) {
            String newPath =
                ItemPathUtils.concatPaths(request.getRequestPath(), files[i].getName());

            request.pushRequestPath(newPath);

            result.add(retrieveItem(repository, repositoryBaseDir, request, files[i]));

            request.popRequestPath();
          }
        }
      } else {
        getLogger()
            .warn(
                "Cannot list directory in repository {}, path \"{}\"",
                RepositoryStringUtils.getHumanizedNameString(repository),
                target.getAbsolutePath());
      }

      return result;
    } else if (target.isFile()) {
      return null;
    } else {
      throw new ItemNotFoundException(request, repository);
    }
  }
  private String generateCatalogPayload(IndexingContext context) throws IOException {
    final MacRequest req =
        new MacRequest(repository.getId(), repositoryContentUrl, artifactInfoFilter);

    // NEXUS-5216: Warn if indexing context is null (indexable=false) for given repository but
    // continue
    // to return the correct empty catalog
    if (context == null) {
      logger.info(
          "Archetype Catalog for repository {} is not buildable as it lacks IndexingContext (indexable=false?).",
          RepositoryStringUtils.getHumanizedNameString(repository));
    }

    // get the catalog
    final ArchetypeCatalog catalog = macPlugin.listArcherypesAsCatalog(req, context);
    // serialize it to XML
    final StringWriter sw = new StringWriter();
    final ArchetypeCatalogXpp3Writer writer = new ArchetypeCatalogXpp3Writer();
    writer.write(sw, catalog);
    return sw.toString();
  }
  @Override
  public Collection<String> evictUnusedItems(ResourceStoreRequest request, final long timestamp) {
    if (!getLocalStatus().shouldServiceRequest()) {
      return Collections.emptyList();
    }

    getLogger()
        .info(
            String.format(
                "Evicting unused items from group repository %s from path \"%s\"",
                RepositoryStringUtils.getHumanizedNameString(this), request.getRequestPath()));

    HashSet<String> result = new HashSet<String>();

    // here, we just iterate over members and call evict
    final List<Repository> members = getMemberRepositories();
    for (Repository repository : members) {
      result.addAll(repository.evictUnusedItems(request, timestamp));
    }

    eventBus().post(new RepositoryEventEvictUnusedItems(this));

    return result;
  }
  public List<StorageItem> doRetrieveItems(ResourceStoreRequest request)
      throws GroupItemNotFoundException, StorageException {
    ArrayList<StorageItem> items = new ArrayList<StorageItem>();

    RepositoryItemUid uid = createUid(request.getRequestPath());

    final boolean isRequestGroupLocalOnly =
        request.isRequestGroupLocalOnly()
            || uid.getBooleanAttributeValue(IsGroupLocalOnlyAttribute.class);

    final HashMap<Repository, Throwable> memberThrowables = new HashMap<Repository, Throwable>();

    if (!isRequestGroupLocalOnly) {
      if (USE_CHARGER_FOR_GROUP_REQUESTS) {
        List<Callable<StorageItem>> callables = new ArrayList<Callable<StorageItem>>();

        for (Repository repository : getRequestRepositories(request)) {
          if (!request.getProcessedRepositories().contains(repository.getId())) {
            callables.add(new ItemRetrieveCallable(getLogger(), repository, request));
          } else {
            if (getLogger().isDebugEnabled()) {
              getLogger()
                  .debug(
                      String.format(
                          "Repository %s member of group %s was already processed during this request! Skipping it from processing. Request: %s",
                          RepositoryStringUtils.getHumanizedNameString(repository),
                          RepositoryStringUtils.getHumanizedNameString(this),
                          request.toString()));
            }
          }
        }

        try {
          return chargerHolder
              .getCharger()
              .submit(callables, new AllArrivedChargeStrategy<StorageItem>(), this)
              .getResult();
        } catch (RejectedExecutionException e) {
          // this will not happen
        } catch (StorageException e) {
          throw e;
        } catch (Exception e) {
          // will not happen, ItemRetrieveCallable supresses all except StorageException!
          // just to make compiler happy
          throw new LocalStorageException("Ouch!", e);
        }
      } else {
        for (Repository repository : getRequestRepositories(request)) {
          if (!request.getProcessedRepositories().contains(repository.getId())) {
            try {
              StorageItem item = repository.retrieveItem(false, request);

              items.add(item);
            } catch (ItemNotFoundException e) {
              // ignored, but bookkeeping happens now
              memberThrowables.put(repository, e);
            } catch (RepositoryNotAvailableException e) {
              if (getLogger().isDebugEnabled()) {
                getLogger()
                    .debug(
                        RepositoryStringUtils.getFormattedMessage(
                            "Member repository %s is not available, request failed.",
                            e.getRepository()));
              }
              // ignored, but bookkeeping happens now
              memberThrowables.put(repository, e);
            } catch (StorageException e) {
              throw e;
            } catch (IllegalOperationException e) {
              getLogger().warn("Member repository request failed", e);
              // ignored, but bookkeeping happens now
              memberThrowables.put(repository, e);
            }
          } else {
            if (getLogger().isDebugEnabled()) {
              getLogger()
                  .debug(
                      String.format(
                          "Repository %s member of group %s was already processed during this request! Skipping it from processing. Request: %s",
                          RepositoryStringUtils.getHumanizedNameString(repository),
                          RepositoryStringUtils.getHumanizedNameString(this),
                          request.toString()));
            }
          }
        }
      }
    }

    if (items.isEmpty()) {
      if (!isRequestGroupLocalOnly) {
        throw new GroupItemNotFoundException(request, this, memberThrowables);
      } else {
        throw new GroupItemNotFoundException(
            reasonFor(
                request,
                this,
                "The %s not found in local storage of group repository %s (no member processing happened).",
                request.getRequestPath(),
                this),
            memberThrowables);
      }
    }

    return items;
  }
  @Override
  protected StorageItem doRetrieveItem(ResourceStoreRequest request)
      throws IllegalOperationException, ItemNotFoundException, StorageException {
    try {
      // local always wins
      return super.doRetrieveItem(request);
    } catch (ItemNotFoundException ignored) {
      // ignored
    }

    boolean hasRequestAuthorizedFlag =
        request.getRequestContext().containsKey(AccessManager.REQUEST_AUTHORIZED);

    if (!hasRequestAuthorizedFlag) {
      request.getRequestContext().put(AccessManager.REQUEST_AUTHORIZED, Boolean.TRUE);
    }

    final HashMap<Repository, Throwable> memberThrowables = new HashMap<Repository, Throwable>();

    try {
      RepositoryItemUid uid = createUid(request.getRequestPath());

      final boolean isRequestGroupLocalOnly =
          request.isRequestGroupLocalOnly()
              || uid.getBooleanAttributeValue(IsGroupLocalOnlyAttribute.class);

      if (!isRequestGroupLocalOnly) {
        if (USE_CHARGER_FOR_GROUP_REQUESTS) {
          List<Callable<StorageItem>> callables = new ArrayList<Callable<StorageItem>>();

          for (Repository repository : getRequestRepositories(request)) {
            if (!request.getProcessedRepositories().contains(repository.getId())) {
              callables.add(new GroupItemRetrieveCallable(getLogger(), repository, request, this));
            } else {
              if (getLogger().isDebugEnabled()) {
                getLogger()
                    .debug(
                        String.format(
                            "Repository %s member of group %s was already processed during this request! Skipping it from processing. Request: %s",
                            RepositoryStringUtils.getHumanizedNameString(repository),
                            RepositoryStringUtils.getHumanizedNameString(this),
                            request.toString()));
              }
            }
          }

          try {
            List<StorageItem> items =
                chargerHolder
                    .getCharger()
                    .submit(callables, new FirstArrivedInOrderChargeStrategy<StorageItem>(), this)
                    .getResult();

            if (items.size() > 0) {
              return items.get(0);
            }
          } catch (RejectedExecutionException e) {
            // this will not happen
          } catch (Exception e) {
            // will not happen, see GroupItemRetrieveCallable class' javadoc, it supresses all of
            // them
            // to make compiler happy
            throw new LocalStorageException("Ouch!", e);
          }
        } else {
          for (Repository repo : getRequestRepositories(request)) {
            if (!request.getProcessedRepositories().contains(repo.getId())) {
              try {
                StorageItem item = repo.retrieveItem(request);

                if (item instanceof StorageCollectionItem) {
                  item = new DefaultStorageCollectionItem(this, request, true, false);
                }

                return item;
              } catch (IllegalOperationException e) {
                // ignored, but bookkeeping happens now
                memberThrowables.put(repo, e);
              } catch (ItemNotFoundException e) {
                // ignored, but bookkeeping happens now
                memberThrowables.put(repo, e);
              } catch (StorageException e) {
                // ignored, but bookkeeping happens now
                memberThrowables.put(repo, e);
              } catch (AccessDeniedException e) {
                // cannot happen, since we add/check for AccessManager.REQUEST_AUTHORIZED flag
                // ignored, but bookkeeping happens now
                memberThrowables.put(repo, e);
              }
            } else {
              if (getLogger().isDebugEnabled()) {
                getLogger()
                    .debug(
                        String.format(
                            "Repository %s member of group %s was already processed during this request! Skipping it from processing. Request: %s",
                            RepositoryStringUtils.getHumanizedNameString(repo),
                            RepositoryStringUtils.getHumanizedNameString(this),
                            request.toString()));
              }
            }
          }
        }
      }
      if (!isRequestGroupLocalOnly) {
        throw new GroupItemNotFoundException(request, this, memberThrowables);
      } else {
        throw new GroupItemNotFoundException(
            reasonFor(
                request,
                this,
                "The %s not found in local storage of group repository %s (no member processing happened).",
                request.getRequestPath(),
                this),
            memberThrowables);
      }
    } finally {
      if (!hasRequestAuthorizedFlag) {
        request.getRequestContext().remove(AccessManager.REQUEST_AUTHORIZED);
      }
    }
  }
  @Override
  protected Collection<StorageItem> doListItems(ResourceStoreRequest request)
      throws ItemNotFoundException, StorageException {
    HashSet<String> names = new HashSet<String>();
    ArrayList<StorageItem> result = new ArrayList<StorageItem>();
    boolean found = false;
    try {
      addItems(names, result, getLocalStorage().listItems(this, request));

      found = true;
    } catch (ItemNotFoundException ignored) {
      // ignored
    }

    RepositoryItemUid uid = createUid(request.getRequestPath());

    final boolean isRequestGroupLocalOnly =
        request.isRequestGroupLocalOnly()
            || uid.getBooleanAttributeValue(IsGroupLocalOnlyAttribute.class);
    final HashMap<Repository, Throwable> memberThrowables = new HashMap<Repository, Throwable>();

    if (!isRequestGroupLocalOnly) {
      for (Repository repo : getMemberRepositories()) {
        if (!request.getProcessedRepositories().contains(repo.getId())) {
          try {
            addItems(names, result, repo.list(false, request));
            found = true;
          } catch (ItemNotFoundException e) {
            // ignored, but bookkeeping happens now
            memberThrowables.put(repo, e);
          } catch (IllegalOperationException e) {
            // ignored, but bookkeeping happens now
            memberThrowables.put(repo, e);
          } catch (StorageException e) {
            // ignored, but bookkeeping happens now
            memberThrowables.put(repo, e);
          }
        } else {
          if (getLogger().isDebugEnabled()) {
            getLogger()
                .debug(
                    String.format(
                        "Repository %s member of group %s was already processed during this request! Skipping it from processing. Request: %s",
                        RepositoryStringUtils.getHumanizedNameString(repo),
                        RepositoryStringUtils.getHumanizedNameString(this),
                        request.toString()));
          }
        }
      }
    }

    if (!found) {
      if (!isRequestGroupLocalOnly) {
        throw new GroupItemNotFoundException(request, this, memberThrowables);
      } else {
        throw new GroupItemNotFoundException(
            reasonFor(
                request,
                this,
                "The %s not found in local storage of group repository %s (no member processing happened).",
                request.getRequestPath(),
                this),
            memberThrowables);
      }
    }

    return result;
  }