private void loadExtensionsFromClassloaders(
      Map<String, DefaultCoreExtension> extensions, DefaultCoreExtensionRepository repository) {
    Set<URL> mavenURLs = ClasspathHelper.forPackage(MAVENPACKAGE);

    ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
    configurationBuilder.setScanners(new ResourcesScanner());
    configurationBuilder.setUrls(mavenURLs);
    configurationBuilder.filterInputsBy(
        new FilterBuilder.Include(FilterBuilder.prefix(MAVENPACKAGE)));

    Reflections reflections = new Reflections(configurationBuilder);

    Set<String> descriptors = reflections.getResources(Predicates.equalTo("pom.xml"));

    for (String descriptor : descriptors) {
      URL descriptorUrl = getClass().getClassLoader().getResource(descriptor);

      try {
        DefaultCoreExtension coreExtension = parseMavenPom(descriptorUrl, repository);

        extensions.put(coreExtension.getId().getId(), coreExtension);
      } catch (Exception e) {
        this.logger.warn("Failed to pase extension descriptor [{}]", descriptorUrl, e);
      }
    }

    // Try to find more

    guess(extensions, repository);
  }
  @Override
  public void updateExtensions(Collection<DefaultCoreExtension> extensions) {
    for (DefaultCoreExtension extension : extensions) {
      try {
        Extension remoteExtension = this.repositoryManager.resolve(extension.getId());

        extension.set(remoteExtension);
      } catch (ResolveException e) {
        this.logger.debug("Can't find remote extension with id [" + extension.getId() + "]", e);
      }
    }
  }
  private String getArtifactId(DefaultCoreExtension extension) throws ResolveException {
    Model model = (Model) extension.getProperty(MavenCoreExtension.PKEY_MAVEN_MODEL);

    String artifactId;
    if (model != null) {
      artifactId = model.getArtifactId();
    } else {
      Matcher matcher = PARSER_ID.matcher(extension.getId().getId());
      if (!matcher.matches()) {
        throw new ResolveException(
            "Bad id "
                + extension.getId().getId()
                + ", expected format is <groupId>:<artifactId>[:<classifier>]");
      }
      artifactId = matcher.group(2);
    }

    return artifactId;
  }
  private void guess(
      Map<String, DefaultCoreExtension> extensions, DefaultCoreExtensionRepository repository) {
    Set<ExtensionDependency> dependencies = new HashSet<ExtensionDependency>();

    for (DefaultCoreExtension coreExtension : extensions.values()) {
      for (ExtensionDependency dependency : coreExtension.getDependencies()) {
        dependencies.add(dependency);
      }
    }

    // Normalize and guess

    Map<String, Object[]> fileNames = new HashMap<String, Object[]>();
    Map<String, Object[]> guessedArtefacts = new HashMap<String, Object[]>();
    Set<URL> urls = ClasspathHelper.forClassLoader();

    for (URL url : urls) {
      try {
        String path = url.toURI().getPath();
        String filename = path.substring(path.lastIndexOf('/') + 1);
        String type = null;

        int extIndex = filename.lastIndexOf('.');
        if (extIndex != -1) {
          type = filename.substring(extIndex + 1);
          filename = filename.substring(0, extIndex);
        }

        int index;
        if (!filename.endsWith(SNAPSHOTSUFFIX)) {
          index = filename.lastIndexOf('-');
        } else {
          index = filename.lastIndexOf('-', filename.length() - SNAPSHOTSUFFIX.length());
        }

        if (index != -1) {
          fileNames.put(filename, new Object[] {url});

          String artefactname = filename.substring(0, index);
          String version = filename.substring(index + 1);

          guessedArtefacts.put(artefactname, new Object[] {version, url, type});
        }
      } catch (Exception e) {
        this.logger.warn("Failed to parse resource name [" + url + "]", e);
      }
    }

    // Try to resolve version no easy to find from the pom.xml
    try {
      for (DefaultCoreExtension coreExtension : extensions.values()) {
        String artifactId = getArtifactId(coreExtension);

        Object[] artefact = guessedArtefacts.get(artifactId);

        if (artefact != null) {
          if (coreExtension.getId().getVersion().getValue().charAt(0) == '$') {
            coreExtension.setId(
                new ExtensionId(coreExtension.getId().getId(), (String) artefact[0]));
            coreExtension.setGuessed(true);
          }

          if (coreExtension.getType().charAt(0) == '$') {
            coreExtension.setType((String) artefact[2]);
            coreExtension.setGuessed(true);
          }
        }
      }

      // Add dependencies that does not provide proper pom.xml resource and can't be found in the
      // classpath
      for (ExtensionDependency extensionDependency : dependencies) {
        Dependency dependency =
            (Dependency)
                extensionDependency.getProperty(MavenCoreExtensionDependency.PKEY_MAVEN_DEPENDENCY);

        if (dependency == null) {
          dependency =
              toDependency(
                  extensionDependency.getId(),
                  extensionDependency.getVersionConstraint().getValue(),
                  null);
        }

        String dependencyId = dependency.getGroupId() + ':' + dependency.getArtifactId();

        DefaultCoreExtension coreExtension = extensions.get(dependencyId);
        if (coreExtension == null) {
          String dependencyFileName = dependency.getArtifactId() + '-' + dependency.getVersion();
          if (dependency.getClassifier() != null) {
            dependencyFileName += '-' + dependency.getClassifier();
            dependencyId += ':' + dependency.getClassifier();
          }

          Object[] filenameArtifact = fileNames.get(dependencyFileName);
          Object[] guessedArtefact = guessedArtefacts.get(dependency.getArtifactId());

          if (filenameArtifact != null) {
            coreExtension =
                new DefaultCoreExtension(
                    repository,
                    (URL) filenameArtifact[0],
                    new ExtensionId(dependencyId, dependency.getVersion()),
                    packagingToType(dependency.getType()));
            coreExtension.setGuessed(true);
          } else if (guessedArtefact != null) {
            coreExtension =
                new DefaultCoreExtension(
                    repository,
                    (URL) guessedArtefact[1],
                    new ExtensionId(dependencyId, (String) guessedArtefact[0]),
                    packagingToType(dependency.getType()));
            coreExtension.setGuessed(true);
          }

          if (coreExtension != null) {
            extensions.put(dependencyId, coreExtension);
          }
        }
      }
    } catch (Exception e) {
      this.logger.warn("Failed to guess extra information about some extensions", e);
    }
  }
  private DefaultCoreExtension parseMavenPom(
      URL descriptorUrl, DefaultCoreExtensionRepository repository)
      throws IOException, XmlPullParserException {
    DefaultCoreExtension coreExtension = null;

    InputStream descriptorStream = descriptorUrl.openStream();
    try {
      MavenXpp3Reader reader = new MavenXpp3Reader();
      Model mavenModel = reader.read(descriptorStream);

      String version = resolveVersion(mavenModel.getVersion(), mavenModel, false);
      String groupId = resolveGroupId(mavenModel.getGroupId(), mavenModel, false);

      URL extensionURL = getExtensionURL(descriptorUrl);

      coreExtension =
          new MavenCoreExtension(
              repository,
              extensionURL,
              new ExtensionId(groupId + ':' + mavenModel.getArtifactId(), version),
              packagingToType(mavenModel.getPackaging()),
              mavenModel);

      coreExtension.setName(mavenModel.getName());
      coreExtension.setSummary(mavenModel.getDescription());
      for (Developer developer : mavenModel.getDevelopers()) {
        URL authorURL = null;
        if (developer.getUrl() != null) {
          try {
            authorURL = new URL(developer.getUrl());
          } catch (MalformedURLException e) {
            // TODO: log ?
          }
        }

        coreExtension.addAuthor(new DefaultExtensionAuthor(developer.getId(), authorURL));
      }
      coreExtension.setWebsite(mavenModel.getUrl());

      // licenses
      for (License license : mavenModel.getLicenses()) {
        coreExtension.addLicense(getExtensionLicense(license));
      }

      // features
      String featuresString = mavenModel.getProperties().getProperty("xwiki.extension.features");
      if (StringUtils.isNotBlank(featuresString)) {
        coreExtension.setFeatures(
            this.converter.<Collection<String>>convert(List.class, featuresString));
      }

      // custom properties
      coreExtension.putProperty("maven.groupId", groupId);
      coreExtension.putProperty("maven.artifactId", mavenModel.getArtifactId());

      // dependencies
      for (Dependency mavenDependency : mavenModel.getDependencies()) {
        if (!mavenDependency.isOptional()
            && (mavenDependency.getScope() == null
                || mavenDependency.getScope().equals("compile")
                || mavenDependency.getScope().equals("runtime"))) {

          String dependencyGroupId = resolveGroupId(mavenDependency.getGroupId(), mavenModel, true);
          String dependencyArtifactId = mavenDependency.getArtifactId();
          String dependencyClassifier = mavenDependency.getClassifier();
          String dependencyVersion = resolveVersion(mavenDependency.getVersion(), mavenModel, true);

          DefaultExtensionDependency extensionDependency =
              new MavenCoreExtensionDependency(
                  toExtensionId(dependencyGroupId, dependencyArtifactId, dependencyClassifier),
                  new DefaultVersionConstraint(dependencyVersion),
                  mavenDependency);

          coreExtension.addDependency(extensionDependency);
        }
      }
    } finally {
      IOUtils.closeQuietly(descriptorStream);
    }

    return coreExtension;
  }