docs: protected File selectResource(String baseLocation, final String symbolicName, final VersionRange versionRange, final boolean performURICheck, final boolean selectBaseBundle) {
          // If the baseLocation is null or the empty string use the default location.
          if (baseLocation == null || "".equals(baseLocation)) {
              baseLocation = getDefaultBaseLocation();
          }
  
          Set<String> baseLocationParts;
  
          // If we have an exact location ...
          if (!!!baseLocation.contains(",")) {
              File candidateFile;
              if (performURICheck) {
                  // ... try to see if we have a URL (actually not sure this is used ever). If it exists return it.
                  try {
                      candidateFile = new File(URI.create(baseLocation));
                      if (candidateFile.exists() && candidateFile.isFile() && candidateFile.isAbsolute()) {
                          return validateR4Bundle(candidateFile);
                      }
                  } catch (IllegalArgumentException iae) {
                      // Just ignore, not a URI, and move on.
                  }
              }
              // If it wasn't a URL then see if we can find it. If we do return it. If we don't we assume
              // the location is a directory and fall through to that processing.
              candidateFile = new File(getRootDirectory(), baseLocation);
              if (candidateFile.exists() && candidateFile.isFile()) {
                  return validateR4Bundle(candidateFile);
              }
              // Prime baseLocationParts with this single baseLocation.
              baseLocationParts = new HashSet<String>();
              baseLocationParts.add(baseLocation);
          } else {
              // If we found a comma we assume we have a comma separated list of directories so split them up.
              baseLocationParts = new HashSet<String>(Arrays.asList(baseLocation.split(",")));
          }
  
          // Loop around all the locations (well DUH!).
          for (String baseLocationPart : baseLocationParts) {
              // Need to trim whitespace in case someone padded the locations in the source.
              baseLocationPart = baseLocationPart.trim();
              // If we haven't seen this location before we need to include the directory looking at the resources in the directory.
              if (!!!isBaseLocationIncluded(baseLocationPart)) {
                  // Make sure we don't include again and then include the directory loading all missed resources into this object.
                  includeBaseLocation(baseLocationPart);
              }
          }
  
          // Now we have loaded everything into memory we grab the candidates with the right symbolic name. If we
          // get nothing back then we will ultimately return a null file.
          List<Resource> candidateResources = getResourcesBySymbolicName(symbolicName);
          if (candidateResources != null) {
              // Sort the candidates (using a sorted set might be more efficient, although 
              // we aren't likely to often select the same resource multiple times).
              // As a result of calling the resource in our example are sorted in this following order:
              // (First entry) a.b/1.0.2.v2, a.b/1.0.1.v1, a.b/1.0.1 (Last entry)
              Collections.sort(candidateResources);
  
              Resource bestMatch = null;
              // Loop around all the candidates.
              for (Resource candidateResource : candidateResources) {
                  // Make sure the candidate is in the baseLocations provided in the selection rules. If it isn't we don't
                  // want it. We also don't want it if it doesn't match the version range passed in. If either of these
                  // conditions are met we just skip.
                  if (!!!baseLocationParts.contains(candidateResource.getBaseLocation()) || !!!versionRange.includes(candidateResource.getVersion())) {
                      continue;
                  }
  
                  // If the best match is null this is the first possible match.
                  if (bestMatch == null) {
                      // If we've got a standard resource here and isn't an IFix then we need to just take the 
                      // top entry, which will give us the highest versioned resource.
                      if (!!!candidateResource.isFix()) {
                          return candidateResource.getFile(); //resource is a basebundle, no action needed for selectBaseBundle
                      } else {
                          // Save the best match, but we need to keep going to make sure the base resource can be found.
                          bestMatch = candidateResource;
                          // Kernel.boot jar when ifixed has no base bundle as the jar keeps the same name due to tooling
                          // having the jar by name on manifest classpaths.  Therefore for this jar there will only be a
                          // single match so return as soon as we have it.
                          if ("com.ibm.ws.kernel.boot".equals(symbolicName)) {
                              return bestMatch.getFile();
                          }
                      }
                  } else {
                      // Fetching here because in the error case we will need to re-fetch.
                      int bestMatchMajor = bestMatch.getVersion().getMajor();
                      int bestMatchMinor = bestMatch.getVersion().getMinor();
                      int bestMatchMicro = bestMatch.getVersion().getMicro();
                      // If the major, minor and micro exist then this is a resource on the same base level (could be another
                      // but older IFix, or the base resource, but it has to be one of them).
                      if (bestMatchMajor == candidateResource.getVersion().getMajor() &&
                          bestMatchMinor == candidateResource.getVersion().getMinor() &&
                          bestMatchMicro == candidateResource.getVersion().getMicro()) {
                          // If we hit something that is not an IFix then we have a valid best IFix so we return it.
                          if (!!!candidateResource.isFix()) {
                              //match was for baseBundle for an ifix, return appropriately.
                              return selectBaseBundle ? candidateResource.getFile() : bestMatch.getFile();
                          }
                      } else {
                          // If we got here then the previous best match did not have a base resource installed. So we
                          // need to output a warning and move on. This message makes an assumption about the way the
                          // resources are named that might not hold, but given no base resource exists we have to make an assumption.
                          warnThatAnIFixWasIgnored(bestMatch.getFile().getName(), bestMatch.getSymbolicName(), bestMatchMajor, bestMatchMinor, bestMatchMicro);
                          // If we can't find an existing match resource for the IFix, then we still need to try and load
                          // a non-IFix version of the resource, if one exists.
                          if (!!!candidateResource.isFix()) {
                              return candidateResource.getFile(); //not ifix, no action needed for selectBaseBundle.
                          } else {
                              bestMatch = candidateResource;
                          }
                      }
                  }
              }
              // If we get here and we have a best match that is not an ifix, we need to return the file for it.
              // This should not happen, as we only store iFixes into bestMatch.. 
              if (bestMatch != null && !!!bestMatch.isFix()) {
                  //not an ifix, so no need to handle selectBaseBundle
                  return bestMatch.getFile();
              }
          }
  
          // If we get here we didn't find a match so just return null.
          return null;
      }