@Nullable
  private static Iterable<Processor> lookupAnnotationProcessors(final APIWrappers.ProcessingContext procContext, @Nullable Iterable<String> processorNames) {
    try {
      Iterable<Processor> processors = null;

      if (hasLocation(procContext.getFileManager(), "ANNOTATION_PROCESSOR_MODULE_PATH")) {
        // this is equivalent to
        //processors = fileManager.getServiceLoader(StandardLocation.locationFor("ANNOTATION_PROCESSOR_MODULE_PATH"), Processor.class);
        // if java modules are involved, they should be properly handled by the fileManager

        //noinspection unchecked
        processors = (ServiceLoader<Processor>)JavaFileManager.class.getMethod("getServiceLoader", JavaFileManager.Location.class, Class.class).invoke(
          procContext.getFileManager(), StandardLocation.locationFor("ANNOTATION_PROCESSOR_MODULE_PATH"), Processor.class
        );
        if (processorNames != null) {
          processors = Iterators.filterWithOrder(processors, Iterators.map(processorNames, new Function<String, BooleanFunction<? super Processor>>() {
            @Override
            public BooleanFunction<? super Processor> fun(final String procName) {
              return new BooleanFunction<Processor>() {
                @Override
                public boolean fun(Processor processor) {
                  return procName.equals(processor.getClass().getName());
                }
              };
            }
          }));
        }
      }
      else {
        final ClassLoader processorClassLoader = procContext.getFileManager().getClassLoader(
          // If processorpath is not explicitly set, use the classpath.
          procContext.getFileManager().hasLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH) ? StandardLocation.ANNOTATION_PROCESSOR_PATH : StandardLocation.CLASS_PATH
        );
        if (processorClassLoader != null) {
          if (processorNames != null) {
            final List<Processor> loaded = new ArrayList<>();
            for (String procName : processorNames) {
              loaded.add((Processor)processorClassLoader.loadClass(procName).getDeclaredConstructor().newInstance());
            }
            processors = loaded;
          }
          else {
            processors = ServiceLoader.load(Processor.class, processorClassLoader);
          }
        }
      }

      if (processors != null) {
        return procContext.wrapProcessors(processors);
      }
    }
    catch (RuntimeException e) {
      throw e;
    }
    catch (Throwable e) {
      throw new RuntimeException(e);
    }
    return null;
  }
@Nullable
  private static Iterable<Processor> lookupAnnotationProcessors(final APIWrappers.ProcessingContext procContext, @Nullable Iterable<String> processorNames)