Program: 143647
Project: 143647
Buggy source:
/** 
 * Recursively resolves an extension dependency.<br> It enforces no extension dependency cycles and also checks for lib conflicts that might occur.<br><br> It also looks for possibilities to update installed extensions so that the given dependency can be installed.
 * @param extension description of the given extension dependency.
 * @param visitedExtensions keeps track of recursively visited extension ids, to avoid cycles. The map's key is the extension id, the map's value is the version.
 * @param visitedLibs keeps track of lib dependencies encountered in current tree path.
 * @return the root node of the resolved dependency tree. Null if the dependency could not be resolved due to missing extension(s)/version(s) or conflict(s).
 */
protected void resolveDependenciesRecursive(DependencyMetadata extension){
  int[] pops=new int[]{0};
  ExtensionNode node=null;
  boolean ok=false;
  LibDependencyDeclaration[][] libsToBeRemovedBecauseOfUpdate=new LibDependencyDeclaration[][]{null};
  if (extension.servoyDependency == null || VersionStringUtils.belongsToInterval(VersionStringUtils.getCurrentServoyVersion(),extension.servoyDependency.minVersion,extension.servoyDependency.maxVersion)) {
    if (visitedExtensions.containsKey(extension.id)) {
      if (VersionStringUtils.sameVersion(visitedExtensions.get(extension.id),extension.version)) {
        ok=true;
      }
 else {
        reasons.add("String_Node_Str" + visitedExtensions.get(extension.id) + "String_Node_Str"+ extension.version+ "String_Node_Str"+ extension.id+ "String_Node_Str");
      }
    }
 else     if (allInstalledExtensions.containsKey(extension.id)) {
      if (VersionStringUtils.sameVersion(allInstalledExtensions.get(extension.id),extension.version)) {
        ok=true;
      }
 else {
        node=new ExtensionNode(extension.id,extension.version,ExtensionNode.REPLACE_RESOLVE);
        ok=handleReplace(extension,libsToBeRemovedBecauseOfUpdate,pops);
      }
    }
 else {
      node=new ExtensionNode(extension.id,extension.version,ExtensionNode.SIMPLE_DEPENDENCY_RESOLVE);
      ok=handleDependencies(extension,pops);
    }
  }
 else {
    reasons.add("String_Node_Str" + extension + "String_Node_Str"+ VersionStringUtils.getCurrentServoyVersion()+ "String_Node_Str"+ extension.servoyDependency.minVersion+ "String_Node_Str"+ extension.servoyDependency.maxVersion+ "String_Node_Str");
  }
  if (ok) {
    if (stillToResolve.size() == 0) {
      if (checkNoLibConflicts(allInstalledLibs,visitedLibs)) {
        if (results == null)         results=new ArrayList<ExtensionNode[]>();
        if (node != null)         treePath.push(node);
        results.add(treePath.toArray(new ExtensionNode[treePath.size()]));
        if (node != null)         treePath.pop();
      }
    }
 else {
      DependencyMetadata[] dependencyVersions=stillToResolve.pop();
      if (node != null) {
        visitedExtensions.put(extension.id,extension.version);
        if (extension.libDependencies != null)         addToLibsMap(extension.libDependencies,visitedLibs);
        treePath.push(node);
        if (libsToBeRemovedBecauseOfUpdate[0] != null)         removeFromLibsMap(libsToBeRemovedBecauseOfUpdate[0],allInstalledLibs);
      }
      for (      DependencyMetadata dependencyVersion : dependencyVersions) {
        resolveDependenciesRecursive(dependencyVersion);
      }
      if (node != null) {
        visitedExtensions.remove(extension.id);
        if (extension.libDependencies != null)         removeFromLibsMap(extension.libDependencies,visitedLibs);
        treePath.pop();
        if (libsToBeRemovedBecauseOfUpdate[0] != null)         addToLibsMap(libsToBeRemovedBecauseOfUpdate[0],allInstalledLibs);
      }
      stillToResolve.push(dependencyVersions);
    }
  }
  while (pops[0]-- > 0)   stillToResolve.pop();
}

Fixed version (ground truth):
/** 
 * Recursively resolves an extension dependency.<br> It enforces no extension dependency cycles and also checks for lib conflicts that might occur.<br><br> It also looks for possibilities to update installed extensions so that the given dependency can be installed.
 * @param extension description of the given extension dependency.
 * @param visitedExtensions keeps track of recursively visited extension ids, to avoid cycles. The map's key is the extension id, the map's value is the version.
 * @param visitedLibs keeps track of lib dependencies encountered in current tree path.
 * @return the root node of the resolved dependency tree. Null if the dependency could not be resolved due to missing extension(s)/version(s) or conflict(s).
 */
protected void resolveDependenciesRecursive(DependencyMetadata extension){
  int[] pops=new int[]{0};
  ExtensionNode node=null;
  boolean ok=false;
  LibDependencyDeclaration[][] libsToBeRemovedBecauseOfUpdate=new LibDependencyDeclaration[][]{null};
  if (extension.servoyDependency == null || VersionStringUtils.belongsToInterval(VersionStringUtils.getCurrentServoyVersion(),extension.servoyDependency.minVersion,extension.servoyDependency.maxVersion)) {
    if (visitedExtensions.containsKey(extension.id)) {
      if (VersionStringUtils.sameVersion(visitedExtensions.get(extension.id),extension.version)) {
        ok=true;
      }
 else {
        reasons.add("String_Node_Str" + visitedExtensions.get(extension.id) + "String_Node_Str"+ extension.version+ "String_Node_Str"+ extension.id+ "String_Node_Str");
      }
    }
 else     if (allInstalledExtensions.containsKey(extension.id)) {
      if (VersionStringUtils.sameVersion(allInstalledExtensions.get(extension.id).version,extension.version)) {
        ok=true;
      }
 else {
        node=new ExtensionNode(extension.id,extension.version,ExtensionNode.REPLACE_RESOLVE);
        ok=handleReplace(extension,libsToBeRemovedBecauseOfUpdate,pops);
      }
    }
 else {
      node=new ExtensionNode(extension.id,extension.version,ExtensionNode.SIMPLE_DEPENDENCY_RESOLVE);
      ok=handleDependencies(extension,pops);
    }
  }
 else {
    reasons.add("String_Node_Str" + extension + "String_Node_Str"+ VersionStringUtils.getCurrentServoyVersion()+ "String_Node_Str"+ extension.servoyDependency.minVersion+ "String_Node_Str"+ extension.servoyDependency.maxVersion+ "String_Node_Str");
  }
  if (ok) {
    if (stillToResolve.size() == 0) {
      if (checkNoLibConflicts(allInstalledLibs,visitedLibs)) {
        if (results == null)         results=new ArrayList<ExtensionNode[]>();
        if (node != null)         treePath.push(node);
        results.add(treePath.toArray(new ExtensionNode[treePath.size()]));
        if (node != null)         treePath.pop();
      }
    }
 else {
      DependencyMetadata[] dependencyVersions=stillToResolve.pop();
      if (node != null) {
        visitedExtensions.put(extension.id,extension.version);
        if (extension.libDependencies != null)         addToLibsMap(extension.libDependencies,visitedLibs);
        treePath.push(node);
        if (libsToBeRemovedBecauseOfUpdate[0] != null)         removeFromLibsMap(libsToBeRemovedBecauseOfUpdate[0],allInstalledLibs);
      }
      for (      DependencyMetadata dependencyVersion : dependencyVersions) {
        resolveDependenciesRecursive(dependencyVersion);
      }
      if (node != null) {
        visitedExtensions.remove(extension.id);
        if (extension.libDependencies != null)         removeFromLibsMap(extension.libDependencies,visitedLibs);
        treePath.pop();
        if (libsToBeRemovedBecauseOfUpdate[0] != null)         addToLibsMap(libsToBeRemovedBecauseOfUpdate[0],allInstalledLibs);
      }
      stillToResolve.push(dependencyVersions);
    }
  }
  while (pops[0]-- > 0)   stillToResolve.pop();
}