docs: public ThreadContextDescriptor captureThreadContext(final Map<String, Map<String, ?>> threadContextConfigurations, final Map<String, String> execProps) {
          int initialCapacity = threadContextConfigurations == null ? 5 : threadContextConfigurations.size() + 5;
          final ThreadContextDescriptorImpl capturedThreadContext = new ThreadContextDescriptorImpl(execProps, initialCapacity, this);
  
          if (!ALL_CONTEXT_TYPES.equals(execProps.get(DEFAULT_CONTEXT))) {
              final List<ThreadContextProvider> configuredProviders = new ArrayList<ThreadContextProvider>(threadContextConfigurations.size());
              final List<Map.Entry<String, Map<String, ?>>> configuredProviderProps = new ArrayList<Map.Entry<String, Map<String, ?>>>(threadContextConfigurations.size());
  
              final List<ThreadContextProvider> alwaysEnabledProviders = new ArrayList<ThreadContextProvider>(alwaysEnabled.size());
              final List<String> alwaysEnabledProviderNames = new ArrayList<String>(alwaysEnabled.size());
  
              // Lazily obtaining services is a privileged operation
              AccessController.doPrivileged(new PrivilegedAction<Void>() {
                  @Override
                  public Void run() {
                      // Identify thread context that is configurable per contextService
                      if (threadContextConfigurations != null)
                          for (Map.Entry<String, Map<String, ?>> threadContextConfig : threadContextConfigurations.entrySet()) {
                              String threadContextProviderName = threadContextConfig.getKey();
                              if (!capturedThreadContext.providerNamesToSkip.contains(threadContextProviderName)) {
                                  ThreadContextProvider provider = threadContextProviders.getService(threadContextProviderName);
                                  if (provider != null) {
                                      configuredProviders.add(provider);
                                      configuredProviderProps.add(threadContextConfig);
                                  }
                              }
                          }
  
                      // Identify context that is always captured per the alwaysCaptureThreadContext service property
                      for (String threadContextProviderName : alwaysEnabled)
                          if (!capturedThreadContext.providerNamesToSkip.contains(threadContextProviderName)) {
                              ThreadContextProvider provider = threadContextProviders.getServiceWithException(threadContextProviderName);
                              alwaysEnabledProviders.add(provider);
                              alwaysEnabledProviderNames.add(threadContextProviderName);
                          }
  
                      return null;
                  }
              });
  
              // capture thread context that is configurable per contextService
              for (int i = 0; i < configuredProviders.size(); i++) {
                  ThreadContextProvider provider = configuredProviders.get(i);
                  Map.Entry<String, Map<String, ?>> threadContextConfig = configuredProviderProps.get(i);
                  ThreadContext context = provider.captureThreadContext(execProps, threadContextConfig.getValue());
                  capturedThreadContext.add(threadContextConfig.getKey(), context);
              }
  
              // context that is always captured per the alwaysCaptureThreadContext service property
              for (int i = 0; i < alwaysEnabledProviders.size(); i++) {
                  ThreadContextProvider provider = alwaysEnabledProviders.get(i);
                  ThreadContext context = provider.captureThreadContext(execProps, null);
                  capturedThreadContext.add(alwaysEnabledProviderNames.get(i), context);
              }
          }
  
          return capturedThreadContext;
      }