private void addRegistryChangeListener(RegistryListener listener) {
   Registry section = registry.getSection(KEY + ".user");
   if (section != null) {
     section.addChangeListener(listener);
   }
   section = registry.getSection(KEY + ".base");
   if (section != null) {
     section.addChangeListener(listener);
   }
 }
 private String removeExpressions(String directory) {
   String value =
       StringUtils.replace(
           directory,
           "${appserver.base}",
           registry.getString("appserver.base", "${appserver.base}"));
   value =
       StringUtils.replace(
           value, "${appserver.home}", registry.getString("appserver.home", "${appserver.home}"));
   return value;
 }
  @Override
  public void removeChangeListener(RegistryListener listener) {
    boolean removed = registryListeners.remove(listener);
    log.debug("RegistryListener: '{}' removed {}", listener, removed);

    Registry section = registry.getSection(KEY + ".user");
    if (section != null) {
      section.removeChangeListener(listener);
    }
    section = registry.getSection(KEY + ".base");
    if (section != null) {
      section.removeChangeListener(listener);
    }
  }
  private Registry readDefaultConfiguration() {
    // if it contains some old configuration, remove it (Archiva 0.9)
    registry.removeSubset(KEY);

    try {
      registry.addConfigurationFromResource(
          "org/apache/archiva/configuration/default-archiva.xml", KEY);
      this.isConfigurationDefaulted = true;
    } catch (RegistryException e) {
      throw new ConfigurationRuntimeException(
          "Fatal error: Unable to find the built-in default configuration and load it into the registry",
          e);
    }
    return registry.getSubset(KEY);
  }
  @PostConstruct
  public void initialize() {

    this.postPolicies = componentContainer.buildMapWithRole(PostDownloadPolicy.class);
    this.prePolicies = componentContainer.buildMapWithRole(PreDownloadPolicy.class);
    this.downloadErrorPolicies = componentContainer.buildMapWithRole(DownloadErrorPolicy.class);
    // Resolve expressions in the userConfigFilename and altConfigFilename
    try {
      ExpressionEvaluator expressionEvaluator = new DefaultExpressionEvaluator();
      expressionEvaluator.addExpressionSource(new SystemPropertyExpressionSource());
      String userConfigFileNameSysProps = System.getProperty("archiva.user.configFileName");
      if (StringUtils.isNotBlank(userConfigFileNameSysProps)) {
        userConfigFilename = userConfigFileNameSysProps;
      } else {
        userConfigFilename = expressionEvaluator.expand(userConfigFilename);
      }
      altConfigFilename = expressionEvaluator.expand(altConfigFilename);
      loadConfiguration();
      handleUpgradeConfiguration();
    } catch (IndeterminateConfigurationException | RegistryException e) {
      throw new RuntimeException("failed during upgrade from previous version" + e.getMessage(), e);
    } catch (EvaluatorException e) {
      throw new RuntimeException(
          "Unable to evaluate expressions found in " + "userConfigFilename or altConfigFilename.",
          e);
    }
    registry.addChangeListener(this);
  }
  private Registry createDefaultConfigurationFile() throws RegistryException {
    // TODO: may not be needed under commons-configuration 1.4 - check

    String contents = "<configuration />";

    String fileLocation = userConfigFilename;

    if (!writeFile("user configuration", userConfigFilename, contents)) {
      fileLocation = altConfigFilename;
      if (!writeFile("alternative configuration", altConfigFilename, contents)) {
        throw new RegistryException(
            "Unable to create configuration file in either user ["
                + userConfigFilename
                + "] or alternative ["
                + altConfigFilename
                + "] locations on disk, usually happens when not allowed to write to those locations.");
      }
    }

    // olamy hackish I know :-)
    contents =
        "<configuration><xml fileName=\""
            + fileLocation
            + "\" config-forceCreate=\"true\" config-name=\"org.apache.archiva.user\"/>"
            + "</configuration>";

    ((CommonsConfigurationRegistry) registry).setProperties(contents);

    registry.initialize();

    for (RegistryListener regListener : registryListeners) {
      addRegistryChangeListener(regListener);
    }

    triggerEvent(ConfigurationEvent.SAVED);

    Registry section = registry.getSection(KEY + ".user");
    return section == null ? new CommonsConfigurationRegistry(new BaseConfiguration()) : section;
  }
  @SuppressWarnings("unchecked")
  @Override
  public synchronized void save(Configuration configuration)
      throws IndeterminateConfigurationException, RegistryException {
    Registry section = registry.getSection(KEY + ".user");
    Registry baseSection = registry.getSection(KEY + ".base");
    if (section == null) {
      section = baseSection;
      if (section == null) {
        section = createDefaultConfigurationFile();
      }
    } else if (baseSection != null) {
      Collection<String> keys = baseSection.getKeys();
      boolean foundList = false;
      for (Iterator<String> i = keys.iterator(); i.hasNext() && !foundList; ) {
        String key = i.next();

        // a little aggressive with the repositoryScanning and databaseScanning - should be no need
        // to split
        // that configuration
        if (key.startsWith("repositories") //
            || key.startsWith("proxyConnectors") //
            || key.startsWith("networkProxies") //
            || key.startsWith("repositoryScanning") //
            || key.startsWith("remoteRepositories") //
            || key.startsWith("managedRepositories") //
            || key.startsWith("repositoryGroups")) //
        {
          foundList = true;
        }
      }

      if (foundList) {
        this.configuration = null;

        throw new IndeterminateConfigurationException(
            "Configuration can not be saved when it is loaded from two sources");
      }
    }

    // escape all cron expressions to handle ','
    escapeCronExpressions(configuration);

    // [MRM-661] Due to a bug in the modello registry writer, we need to take these out by hand.
    // They'll be put back by the writer.
    if (configuration.getManagedRepositories().isEmpty() && section != null) {
      section.removeSubset("managedRepositories");
    }
    if (configuration.getRemoteRepositories().isEmpty() && section != null) {
      section.removeSubset("remoteRepositories");
    }
    if (configuration.getProxyConnectors().isEmpty() && section != null) {
      section.removeSubset("proxyConnectors");
    }
    if (configuration.getNetworkProxies().isEmpty() && section != null) {
      section.removeSubset("networkProxies");
    }
    if (configuration.getLegacyArtifactPaths().isEmpty() && section != null) {
      section.removeSubset("legacyArtifactPaths");
    }
    if (configuration.getRepositoryGroups().isEmpty() && section != null) {
      section.removeSubset("repositoryGroups");
    }
    if (configuration.getRepositoryScanning() != null) {
      if (configuration.getRepositoryScanning().getKnownContentConsumers().isEmpty()
          && section != null) {
        section.removeSubset("repositoryScanning.knownContentConsumers");
      }
      if (configuration.getRepositoryScanning().getInvalidContentConsumers().isEmpty()
          && section != null) {
        section.removeSubset("repositoryScanning.invalidContentConsumers");
      }
    }

    new ConfigurationRegistryWriter().write(configuration, section);
    section.save();

    this.configuration = unescapeExpressions(configuration);

    triggerEvent(ConfigurationEvent.SAVED);
  }
  @SuppressWarnings("unchecked")
  private Configuration load() {
    // TODO: should this be the same as section? make sure unnamed sections still work (eg, sys
    // properties)
    Registry subset = registry.getSubset(KEY);
    if (subset.getString("version") == null) {
      // a little autodetection of v1, even if version is omitted (this was previously allowed)
      if (subset.getSubset("repositoryScanning").isEmpty()) {
        // only for empty, or v < 1
        subset = readDefaultConfiguration();
      }
    }

    Configuration config = new ConfigurationRegistryReader().read(subset);

    config.getRepositoryGroups();
    config.getRepositoryGroupsAsMap();
    if (!config.getRepositories().isEmpty()) {
      for (V1RepositoryConfiguration r : config.getRepositories()) {
        r.setScanned(r.isIndexed());

        if (StringUtils.startsWith(r.getUrl(), "file://")) {
          r.setLocation(r.getUrl().substring(7));
          config.addManagedRepository(r);
        } else if (StringUtils.startsWith(r.getUrl(), "file:")) {
          r.setLocation(r.getUrl().substring(5));
          config.addManagedRepository(r);
        } else if (StringUtils.isEmpty(r.getUrl())) {
          // in case of empty url we can consider it as a managed one
          // check if location is null
          // file://${appserver.base}/repositories/${id}
          if (StringUtils.isEmpty(r.getLocation())) {
            r.setLocation("file://${appserver.base}/repositories/" + r.getId());
          }
          config.addManagedRepository(r);
        } else {
          RemoteRepositoryConfiguration repo = new RemoteRepositoryConfiguration();
          repo.setId(r.getId());
          repo.setLayout(r.getLayout());
          repo.setName(r.getName());
          repo.setUrl(r.getUrl());
          config.addRemoteRepository(repo);
        }
      }

      // Prevent duplicate repositories from showing up.
      config.getRepositories().clear();

      registry.removeSubset(KEY + ".repositories");
    }

    if (!CollectionUtils.isEmpty(config.getRemoteRepositories())) {
      List<RemoteRepositoryConfiguration> remoteRepos = config.getRemoteRepositories();
      for (RemoteRepositoryConfiguration repo : remoteRepos) {
        // [MRM-582] Remote Repositories with empty <username> and <password> fields shouldn't be
        // created in configuration.
        if (StringUtils.isBlank(repo.getUsername())) {
          repo.setUsername(null);
        }

        if (StringUtils.isBlank(repo.getPassword())) {
          repo.setPassword(null);
        }
      }
    }

    if (!config.getProxyConnectors().isEmpty()) {
      // Fix Proxy Connector Settings.

      // Create a copy of the list to read from (to prevent concurrent modification exceptions)
      List<ProxyConnectorConfiguration> proxyConnectorList =
          new ArrayList<>(config.getProxyConnectors());
      // Remove the old connector list.
      config.getProxyConnectors().clear();

      for (ProxyConnectorConfiguration connector : proxyConnectorList) {
        // Fix policies
        boolean connectorValid = true;

        Map<String, String> policies = new HashMap<>();
        // Make copy of policies
        policies.putAll(connector.getPolicies());
        // Clear out policies
        connector.getPolicies().clear();

        // Work thru policies. cleaning them up.
        for (Entry<String, String> entry : policies.entrySet()) {
          String policyId = entry.getKey();
          String setting = entry.getValue();

          // Upgrade old policy settings.
          if ("releases".equals(policyId) || "snapshots".equals(policyId)) {
            if ("ignored".equals(setting)) {
              setting = AbstractUpdatePolicy.ALWAYS;
            } else if ("disabled".equals(setting)) {
              setting = AbstractUpdatePolicy.NEVER;
            }
          } else if ("cache-failures".equals(policyId)) {
            if ("ignored".equals(setting)) {
              setting = CachedFailuresPolicy.NO;
            } else if ("cached".equals(setting)) {
              setting = CachedFailuresPolicy.YES;
            }
          } else if ("checksum".equals(policyId)) {
            if ("ignored".equals(setting)) {
              setting = ChecksumPolicy.IGNORE;
            }
          }

          // Validate existance of policy key.
          if (policyExists(policyId)) {
            Policy policy = findPolicy(policyId);
            // Does option exist?
            if (!policy.getOptions().contains(setting)) {
              setting = policy.getDefaultOption();
            }
            connector.addPolicy(policyId, setting);
          } else {
            // Policy key doesn't exist. Don't add it to golden version.
            log.warn("Policy [{}] does not exist.", policyId);
          }
        }

        if (connectorValid) {
          config.addProxyConnector(connector);
        }
      }

      // Normalize the order fields in the proxy connectors.
      Map<String, java.util.List<ProxyConnectorConfiguration>> proxyConnectorMap =
          config.getProxyConnectorAsMap();

      for (List<ProxyConnectorConfiguration> connectors : proxyConnectorMap.values()) {
        // Sort connectors by order field.
        Collections.sort(connectors, ProxyConnectorConfigurationOrderComparator.getInstance());

        // Normalize the order field values.
        int order = 1;
        for (ProxyConnectorConfiguration connector : connectors) {
          connector.setOrder(order++);
        }
      }
    }

    return config;
  }