@SuppressWarnings("unchecked")
    public List<IvyModuleInfo> call() throws Throwable {
      File ws = new File(workspace);
      FileSet ivyFiles = Util.createFileSet(ws, ivyFilePattern, ivyFileExcludePattern);
      final PrintStream logger = listener.getLogger();

      Ivy ivy = getIvy(logger);
      HashMap<ModuleDescriptor, String> moduleDescriptors = new HashMap<ModuleDescriptor, String>();
      for (String ivyFilePath : ivyFiles.getDirectoryScanner().getIncludedFiles()) {
        final File ivyFile = new File(ws, ivyFilePath);

        ModuleDescriptor module =
            (ModuleDescriptor)
                ivy.execute(
                    new IvyCallback() {
                      public Object doInIvyContext(Ivy ivy, IvyContext context) {
                        try {
                          return ModuleDescriptorParserRegistry.getInstance()
                              .parseDescriptor(
                                  ivy.getSettings(),
                                  ivyFile.toURI().toURL(),
                                  ivy.getSettings().doValidate());
                        } catch (MalformedURLException e) {
                          logger.println("The URL is malformed : " + ivyFile);
                          return null;
                        } catch (ParseException e) {
                          logger.println("Parsing error while reading the ivy file " + ivyFile);
                          return null;
                        } catch (IOException e) {
                          logger.println("I/O error while reading the ivy file " + ivyFile);
                          return null;
                        }
                      }
                    });
        moduleDescriptors.put(module, ivyFilePath.replace('\\', '/'));
      }

      List<IvyModuleInfo> infos = new ArrayList<IvyModuleInfo>();
      List<ModuleDescriptor> sortedModuleDescriptors =
          ivy.sortModuleDescriptors(moduleDescriptors.keySet(), SortOptions.DEFAULT);
      for (ModuleDescriptor moduleDescriptor : sortedModuleDescriptors) {
        infos.add(new IvyModuleInfo(moduleDescriptor, moduleDescriptors.get(moduleDescriptor)));
      }

      if (verbose) {
        for (IvyModuleInfo moduleInfo : infos) {
          logger.printf(
              "Discovered module %s at %s.\n",
              moduleInfo.displayName, moduleInfo.relativePathToDescriptor);
        }
      }

      return infos;
    }