/**
   * will mirror a feature from remote site, supports features stored on remote server, or features
   * stored on other servers, via an absolute url in the site.xml
   *
   * @param site
   * @param featureRef
   * @param mirrored
   * @throws StorageException
   * @throws IllegalOperationException
   */
  private void mirrorFeature(UpdateSite site, IFeatureRef featureRef, Set<String> mirrored)
      throws StorageException, IllegalOperationException {
    ResourceStoreRequest request = createResourceStoreRequest(featureRef);

    if (request == null || !mirrored.add(request.getRequestPath())) {
      return;
    }

    getLogger().debug("Mirroring feature " + featureRef);

    Feature feature = null;

    // request url will only be set when an absolute uri is found
    if (request.getRequestUrl() != null) {
      String absoluteUrl = request.getRequestUrl();
      request.setRequestUrl(null);

      feature = mirrorAbsoluteFeature(absoluteUrl, featureRef, request, mirrored);
    } else {
      feature = mirrorRelativeFeature(featureRef, request, mirrored);
    }

    if (feature != null) {
      List<PluginRef> includedPlugins = feature.getPlugins();
      List<Feature.FeatureRef> includedFeatures = feature.getIncludedFeatures();

      getLogger()
          .debug(
              featureRef
                  + " includes "
                  + includedFeatures.size()
                  + " features and "
                  + includedPlugins.size()
                  + " plugins");

      for (PluginRef plugin : includedPlugins) {
        mirrorPlugin(site, plugin, mirrored);
      }

      for (IFeatureRef includedFeature : includedFeatures) {
        mirrorFeature(site, includedFeature, mirrored);
      }
    }
  }