docs: private final String updateWithLibraries(BundleContext bundleContext,
                                               String applicationName,
                                               String declaringApplication,
                                               String className,
                                               String url,
                                               Hashtable<String, Object> driverProps,
                                               Hashtable<String, Object> dsSvcProps) throws Exception {
          final boolean trace = TraceComponent.isAnyTracingEnabled();
          if (trace && tc.isEntryEnabled())
              Tr.entry(tc, "updateWithLibraries", applicationName, className);
  
          ConfigurationAdmin configAdmin = configAdminRef.getServiceWithException();
  
          // Find the application
          Configuration[] classloaderConfigs = null;
          ServiceReference<?>[] refs = DataSourceService.priv.getServiceReferences(bundleContext,"com.ibm.wsspi.application.Application", FilterUtils.createPropertyFilter("name", declaringApplication));
          if (refs != null && refs.length > 0) {
              ServiceReference<?> appRef = refs[0];
              String parentPid = (String) appRef.getProperty(Constants.SERVICE_PID);
              String sourcePid = (String) appRef.getProperty("ibm.extends.source.pid");
              if (sourcePid != null) {
                  parentPid = sourcePid;
              }
              // Find the classloaders for the application
              StringBuilder classloaderFilter = new StringBuilder(200);
              classloaderFilter.append("(&");
              classloaderFilter.append(FilterUtils.createPropertyFilter("service.factoryPid", "com.ibm.ws.classloading.classloader"));
              classloaderFilter.append(FilterUtils.createPropertyFilter("config.parentPID", parentPid));
              classloaderFilter.append(')');
              if (trace && tc.isDebugEnabled())
                  Tr.debug(tc, "filter for classloaders", classloaderFilter);
              if (classloaderFilter.length() > 3)
                  classloaderConfigs = configAdmin.listConfigurations(classloaderFilter.toString());
          }
  
          // Find the shared libraries for the classloaders
          StringBuilder commonLibraryFilter = new StringBuilder(500);
          StringBuilder libraryFilter = new StringBuilder(500);
          commonLibraryFilter.append("(|");
          libraryFilter.append("(|");
          
          if (classloaderConfigs != null) {
              for (Configuration classloaderConfig : classloaderConfigs) {
                  Dictionary<?, ?> classloaderProps = classloaderConfig.getProperties();
                  if (trace && tc.isDebugEnabled())
                      Tr.debug(tc, "classloader", classloaderProps);
  
                  // Do not check for privateLibraryRef for java:global data source definitions, applicationName is null when java:global is used
                  if (applicationName != null) {
                      Object privateLibraryRef = classloaderProps.get("privateLibraryRef");
                      if (privateLibraryRef != null && privateLibraryRef instanceof String[])
                          for (String pid : (String[]) privateLibraryRef)
                              libraryFilter.append(FilterUtils.createPropertyFilter(Constants.SERVICE_PID, pid));
                  }
  
                  Object commonLibraryRef = classloaderProps.get("commonLibraryRef");
                  if (commonLibraryRef != null && commonLibraryRef instanceof String[])
                      for (String pid : (String[]) commonLibraryRef)
                          commonLibraryFilter.append(FilterUtils.createPropertyFilter(Constants.SERVICE_PID, pid));
              }
          }
  
          commonLibraryFilter.append(')');
          libraryFilter.append(')');
          if (trace && tc.isDebugEnabled())
              Tr.debug(tc, "filters for libraries", commonLibraryFilter, libraryFilter);
          // Give commonLibraryRef higher priority than libraryRef by adding it first
          List<ServiceReference<Library>> libraryRefs = new LinkedList<ServiceReference<Library>>();
          if (commonLibraryFilter.length() > 3)
              libraryRefs.addAll(DataSourceService.priv.getServiceReferences(bundleContext,Library.class, commonLibraryFilter.toString()));
          if (libraryFilter.length() > 3)
              libraryRefs.addAll(DataSourceService.priv.getServiceReferences(bundleContext,Library.class, libraryFilter.toString()));
          
          // If no commonLibraryRef or privateLibraryRef was specified, use the global shared lib
          if(libraryRefs.size() == 0){
              if(trace && tc.isDebugEnabled())
                  Tr.debug(tc, "No direct library refs found on datasource, using global shared lib");
              StringBuilder globalLibFilter = new StringBuilder("(&");
              globalLibFilter.append(FilterUtils.createPropertyFilter("service.factoryPid", "com.ibm.ws.classloading.sharedlibrary"));
              globalLibFilter.append(FilterUtils.createPropertyFilter("id", "global"));
              globalLibFilter.append(")");
              Collection<ServiceReference<Library>> globalLib = DataSourceService.priv.getServiceReferences(bundleContext, Library.class, globalLibFilter.toString());
              libraryRefs.addAll(globalLib);
          }
  
          if (trace && tc.isDebugEnabled())
              Tr.debug(tc, "libraries", libraryRefs.toArray());
  
          // this structure is populated only if className and url properties are absent.
          String[][] dsClassInfo = new String[JDBCDrivers.NUM_DATA_SOURCE_INTERFACES][2];
          final int CLASS_NAME = 0, LIBRARY_PID = 1; // indices for the second dimension
  
          // determine if we need to search for an implementation class, and if so, of which type(s)
          int[] dsTypeSearchOrder;
          Set<String> searchedLibraryFiles = new TreeSet<String>();
          Set<String> searchedPackages;
          
          boolean hasImplClassName = className != null && className.length() > 0;
          if (hasImplClassName) {
              if (XADataSource.class.getName().equals(className)) {
                  dsTypeSearchOrder = new int[] { JDBCDrivers.XA_DATA_SOURCE };
                  searchedPackages = new TreeSet<String>();
                  hasImplClassName = false;
              } else if (ConnectionPoolDataSource.class.getName().equals(className)) {
                  dsTypeSearchOrder = new int[] { JDBCDrivers.CONNECTION_POOL_DATA_SOURCE };
                  searchedPackages = new TreeSet<String>();
                  hasImplClassName = false;
              } else if (DataSource.class.getName().equals(className)) {
                  dsTypeSearchOrder = new int[] { JDBCDrivers.DATA_SOURCE };
                  searchedPackages = new TreeSet<String>();
                  hasImplClassName = false;
              } else if (Driver.class.getName().equals(className)) {
                  dsTypeSearchOrder = null;
                  searchedPackages = Collections.singleton("META-INF/services/java.sql.Driver");
                  hasImplClassName = false;
              } else {
                  dsTypeSearchOrder = null; // if we know the impl class, there is no need to search for one
                  searchedPackages = null;
              }
          } else if (url == null) {
              dsTypeSearchOrder = new int[] { JDBCDrivers.XA_DATA_SOURCE, JDBCDrivers.CONNECTION_POOL_DATA_SOURCE, JDBCDrivers.DATA_SOURCE };
              searchedPackages = new TreeSet<String>();
          } else { // assume java.sql.Driver due to presence of URL
              dsTypeSearchOrder = null;
              searchedPackages = Collections.singleton("META-INF/services/java.sql.Driver");
          }
  
          // Determine which shared library can load className
          for (ServiceReference<Library> libraryRef : libraryRefs) {
              Library library = DataSourceService.priv.getService(bundleContext,libraryRef);
              try {
                  String libraryPid = (String) libraryRef.getProperty(Constants.SERVICE_PID);
                  if (library == null) {
                      if (trace && tc.isDebugEnabled())
                          Tr.debug(tc, "library not found", libraryPid);
                  } else {
                      try {
                          ClassLoader loader = AdapterUtil.getClassLoaderWithPriv(library);
  
                          String type = null;
                          if (hasImplClassName) {
                              Class<?> cl = DataSourceService.priv.loadClass(loader, className);
                              type = XADataSource.class.isAssignableFrom(cl) ? XADataSource.class.getName()
                                   : ConnectionPoolDataSource.class.isAssignableFrom(cl) ? ConnectionPoolDataSource.class.getName()
                                   : DataSource.class.isAssignableFrom(cl) ? DataSource.class.getName()
                                   : Driver.class.getName();
                          } else {
                              searchedLibraryFiles.addAll(JDBCDriverService.getClasspath(library, false));
                              if (dsTypeSearchOrder == null) {
                                  type = Driver.class.getName();
                                  for (Iterator<Driver> it = ServiceLoader.load(Driver.class, loader).iterator(); it.hasNext(); ) {
                                      Driver driver = it.next();
                                      if (trace && tc.isDebugEnabled())
                                          Tr.debug(this, tc, "trying driver", driver);
                                      try {
                                          if (driver.acceptsURL(url)) {
                                              if (trace && tc.isDebugEnabled())
                                                  Tr.debug(this, tc, driver + " accepts " + PropertyService.filterURL(url));
                                              className = driver.getClass().getName();
                                              break;
                                          } else {
                                              if (trace && tc.isDebugEnabled())
                                                  Tr.debug(this, tc, driver + " does not accept " + PropertyService.filterURL(url));
                                          }
                                      } catch (SQLException x) {
                                          if (trace && tc.isDebugEnabled())
                                              Tr.debug(this, tc, driver + " does not accept " + PropertyService.filterURL(url), x);
                                      }
                                  }
                              } else {
                                  SimpleEntry<Integer, String> dsEntry = JDBCDrivers.inferDataSourceClassFromDriver(loader,
                                                                                                                    searchedPackages,
                                                                                                                    dsTypeSearchOrder);
                                  if (dsEntry != null) {
                                      int dsType = dsEntry.getKey();
                                      if (dsClassInfo[dsType][CLASS_NAME] == null) {
                                          dsClassInfo[dsType][CLASS_NAME] = dsEntry.getValue();
                                          dsClassInfo[dsType][LIBRARY_PID] = libraryPid;
                                      }
                                  }
                              }
                          }
  
                          if (className != null && type != null) {
                              driverProps.put(JDBCDriverService.LIBRARY_REF, new String[] { libraryPid });
                              driverProps.put(JDBCDriverService.TARGET_LIBRARY, FilterUtils.createPropertyFilter("service.pid", libraryPid));
                              driverProps.put(type, className);
                              dsSvcProps.put(DSConfig.TYPE, type);
  
                              if (trace && tc.isEntryEnabled())
                                  Tr.exit(tc, "updateWithLibraries", driverProps);
                              return className;
                          }
                      } catch (ClassNotFoundException x) {
                          if (trace && tc.isDebugEnabled())
                              Tr.debug(tc, className + " not found in", libraryPid);
                          searchedLibraryFiles.addAll(JDBCDriverService.getClasspath(library, false));
                      } catch (Exception x) {
                          FFDCFilter.processException(x, DataSourceResourceFactoryBuilder.class.getName(), "444", new Object[] { libraryRef });
                          if (trace && tc.isDebugEnabled())
                              Tr.debug(tc, libraryRef.toString(), x);
                          searchedLibraryFiles.addAll(JDBCDriverService.getClasspath(library, false));
                          // Continue to try other libraryRefs
                      }
                  }
              } finally {
                  bundleContext.ungetService(libraryRef);
              }
          }
  
          // Inferred data source class name when className and url properties are absent 
          for (int dsType : new int[] { JDBCDrivers.XA_DATA_SOURCE, JDBCDrivers.CONNECTION_POOL_DATA_SOURCE, JDBCDrivers.DATA_SOURCE })
              if (dsClassInfo[dsType][CLASS_NAME] != null) {
                  String type = dsType == JDBCDrivers.XA_DATA_SOURCE ? XADataSource.class.getName()
                              : dsType == JDBCDrivers.CONNECTION_POOL_DATA_SOURCE ? ConnectionPoolDataSource.class.getName()
                              : DataSource.class.getName();
                  driverProps.put(JDBCDriverService.LIBRARY_REF, new String[] { dsClassInfo[dsType][LIBRARY_PID] });
                  driverProps.put(JDBCDriverService.TARGET_LIBRARY, FilterUtils.createPropertyFilter("service.pid", dsClassInfo[dsType][LIBRARY_PID]));
                  driverProps.put(type, dsClassInfo[dsType][CLASS_NAME]);
                  dsSvcProps.put(DSConfig.TYPE, type);
  
                  if (trace && tc.isEntryEnabled())
                      Tr.exit(tc, "updateWithLibraries", driverProps);
                  return dsClassInfo[dsType][CLASS_NAME];
              }
  
          String message;
          if (searchedPackages == null) {
              // className couldn't be found in any of the shared libraries
              message = ConnectorService.getMessage("MISSING_LIBRARY_J2CA8022", declaringApplication, className, DataSourceService.DATASOURCE,
                                                    dsSvcProps.get(DataSourceService.JNDI_NAME));
          } else {
              List<String> types = dsTypeSearchOrder == null ? Collections.singletonList("java.sql.Driver"): new ArrayList<String>(dsTypeSearchOrder.length);
              if (dsTypeSearchOrder != null)
                  for (int dsType : dsTypeSearchOrder)
                      switch (dsType) {
                          case JDBCDrivers.DATA_SOURCE: types.add("javax.sql.DataSource"); break;
                          case JDBCDrivers.CONNECTION_POOL_DATA_SOURCE : types.add("javax.sql.ConnectionPoolDataSource"); break;
                          case JDBCDrivers.XA_DATA_SOURCE : types.add("javax.sql.XADataSource"); break;
                      }
              message = AdapterUtil.getNLSMessage("DSRA4001.no.suitable.driver.nested", types, dsSvcProps.get(DataSourceService.JNDI_NAME),
                                                  searchedLibraryFiles, searchedPackages);
          }
          SQLNonTransientException x = new SQLNonTransientException(message);
  
          if (trace && tc.isEntryEnabled())
              Tr.exit(tc, "updateWithLibraries", x);
          throw x;
      }