@Override
 protected void shouldTryRemote(final ResourceStoreRequest request)
     throws IllegalOperationException, ItemNotFoundException {
   // do super first
   super.shouldTryRemote(request);
   // if here, super did not throw any exception, so let's continue
   // apply autorouting filter to "normal" requests only, not hidden (which is meta or plain
   // hidden)
   final RepositoryItemUid uid = createUid(request.getRequestPath());
   if (!uid.getBooleanAttributeValue(IsHiddenAttribute.class)) {
     // but filter it only if request is not marked as NFS
     if (!request.getRequestContext().containsKey(Manager.ROUTING_REQUEST_NFS_FLAG_KEY)) {
       final boolean proxyFilterAllowed = getProxyRequestFilter().allowed(this, request);
       if (!proxyFilterAllowed) {
         throw new ItemNotFoundException(
             ItemNotFoundException.reasonFor(
                 request,
                 this,
                 "Automatic routing filter rejected remote request for path %s from %s",
                 request.getRequestPath(),
                 this));
       }
     }
   }
 }
  private void fixRemoteUrl(ResourceStoreRequest request) {
    if (overwriteRemoteUrl != null) {
      return;
    }

    if (P2Constants.SITE_XML.equals(request.getRequestPath())) {
      return;
    }

    try {
      RepositoryItemUid siteUID = createUid(P2Constants.SITE_XML);
      ResourceStoreRequest siteRequest = new ResourceStoreRequest(siteUID.getPath());
      StorageFileItem siteItem;
      try {
        siteItem = (StorageFileItem) getLocalStorage().retrieveItem(this, siteRequest);
      } catch (ItemNotFoundException e) {
        siteItem =
            (StorageFileItem) getRemoteStorage().retrieveItem(this, siteRequest, getRemoteUrl());
      }

      PlexusConfiguration plexusConfig =
          new XmlPlexusConfiguration(
              Xpp3DomBuilder.build(new InputStreamReader(siteItem.getInputStream())));

      this.overwriteRemoteUrl = plexusConfig.getAttribute("url");
      getLogger()
          .info("Remote update site does overwrite the remote url " + this.overwriteRemoteUrl);
    } catch (Exception e) {
      getLogger().debug(e.getMessage(), e);
      this.overwriteRemoteUrl = "";
    }
  }
 public Boolean getValueFor(RepositoryItemUid subject) {
   // /.nexus/attributes
   if (subject.getPath() != null) {
     return subject.getPath().startsWith("/.nexus/attributes");
   } else {
     return false;
   }
 }
  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;
  }
 @Override
 public String getPath() {
   return uid.getPath();
 }
 @Override
 public Repository getRepository() {
   return uid.getRepository();
 }
  public Object retrieveView(
      ResourceStore store, ResourceStoreRequest request, StorageItem item, Request req)
      throws IOException {
    RepositoryItemUid itemUid = null;

    if (item == null) {
      if (store instanceof RepositoryRouter) {
        RepositoryRouter repositoryRouter = (RepositoryRouter) store;
        // item is either not present or is not here yet (remote index)
        // the we can "simulate" what route would be used to get it, and just get info from the
        // route
        RequestRoute route;

        try {
          route = repositoryRouter.getRequestRouteForRequest(request);
        } catch (ItemNotFoundException e) {
          // this is thrown while getting routes for any path "outside" of legal ones is given
          // like /content/foo/bar, since 2nd pathelem may be "repositories", "groups", "shadows",
          // etc
          // (depends on
          // type of registered reposes)
          return null;
        }

        // request would be processed by targeted repository
        Repository itemRepository = route.getTargetedRepository();

        // create an UID against that repository
        itemUid = itemRepository.createUid(route.getRepositoryPath());
      } else if (store instanceof Repository) {
        itemUid = ((Repository) store).createUid(request.getRequestPath());
      } else {
        // this is highly unbelievable, unless Core gets extended by 3rd party
        return null;
      }
    } else {
      itemUid = item.getRepositoryItemUid();

      if ((item instanceof StorageLinkItem) && dereferenceLinks()) {
        // TODO: we may have "deeper" links too! Implement this properly!
        try {
          item =
              repositoryRouter.dereferenceLink(
                  (StorageLinkItem) item,
                  request.isRequestLocalOnly(),
                  request.isRequestRemoteOnly());
        } catch (Exception e) {
          getLogger()
              .warn("Failed to dereference the storagelink " + item.getRepositoryItemUid(), e);

          // leave item unchanged
        }
      }
    }

    // so, we ended with:
    // itemUid is always populated, hence we have Repository and repository path
    // so, item may be null or non-null, if non-null, it may be link

    // check for item not found finally. Those may be allowed in proxy repositories only.
    if (item == null && !processNotFoundItems(itemUid.getRepository())) {
      // return not-applicable. This is not a proxy repository, and the item is not found. Since it
      // is not
      // proxy repo, it will be never cached from remote too, simply, it is not here.
      return null;
    }

    return retrieveView(request, itemUid, item, req);
  }
  private void mirrorUpdateSite(boolean force)
      throws StorageException, IllegalOperationException, UnsupportedStorageOperationException {
    UpdateSite site;
    try {
      RepositoryItemUid siteUID = createUid(P2Constants.SITE_XML);
      String oldSha1 = null;

      ResourceStoreRequest request = new ResourceStoreRequest(siteUID.getPath());

      try {
        oldSha1 =
            getLocalStorage()
                .retrieveItem(this, request)
                .getAttributes()
                .get(DigestCalculatingInspector.DIGEST_SHA1_KEY);
      } catch (ItemNotFoundException e) {
        // it's okay
      }

      StorageFileItem siteItem = (StorageFileItem) doRetrieveRemoteItem(request);

      if (!force
          && oldSha1 != null
          && oldSha1.equals(
              siteItem.getAttributes().get(DigestCalculatingInspector.DIGEST_SHA1_KEY))) {
        return;
      }
      site = UpdateSite.read(siteItem.getInputStream());
    } catch (Exception e) {
      throw new StorageException("Could not read site.xml", e);
    }

    List<FeatureRef> features = site.getFeatures();

    getLogger().info("Mirroring " + features.size() + " features from update site " + getName());

    final Set<String> mirrored = new HashSet<String>();

    for (IFeatureRef feature : features) {
      mirrorFeature(site, feature, mirrored);
    }

    ResourceStoreRequest root = new ResourceStoreRequest(RepositoryItemUid.PATH_ROOT);

    DefaultWalkerContext ctx = new DefaultWalkerContext(this, root, filter);
    ctx.getContext().put("mirrored", mirrored);
    ctx.getProcessors()
        .add(
            new AbstractWalkerProcessor() {
              @SuppressWarnings("unchecked")
              @Override
              public void processItem(WalkerContext context, StorageItem item) throws Exception {
                Set<String> mirrored = (Set<String>) context.getContext().get("mirrored");

                if (item.getRepositoryItemUid().getBooleanAttributeValue(IsHiddenAttribute.class)) {
                  return;
                }

                if (item instanceof StorageFileItem
                    && !mirrored.contains(item.getPath().substring(1))) {
                  doDeleteItem(new ResourceStoreRequest(item.getPath()));
                }
              }
            });
    getWalker().walk(ctx);

    getLogger().debug("Generating P2 metadata for Eclipse Update Site " + getName());

    File baseDir = getLocalStorage().getBaseDir(this, root);
    File metadataDir = new File(baseDir, ".p2");

    try {
      FileUtils.deleteDirectory(metadataDir);
    } catch (IOException e) {
      getLogger().warn("Unexpected IOException", e);
    }

    p2.generateSiteMetadata(baseDir, metadataDir, getName());

    try {
      importFile(metadataDir, P2Constants.ARTIFACTS_PATH);
      importFile(metadataDir, P2Constants.CONTENT_PATH);
      FileUtils.deleteDirectory(metadataDir);
    } catch (IOException e) {
      // TODO this can actually happen on Windows
      getLogger().warn("Unexpected IOException", e);
    }
  }