/**
  * Instruments the given directory, reading each .class file, processing it, and writing it back
  * to the filesystem
  *
  * @param configurer an {@link InstrumenterConfigurer} that will setup the actual {@link
  *     Instrumenter} that will be used to process the directory
  * @param processDirectory the directory with .class files to process
  * @param extraPath a string containing a list of additional paths to add to the classpath used on
  *     instrumentation. This string is system-dependent, using the platform separator and
  *     directory separator
  * @throws Exception
  * @see File#pathSeparator
  * @see File#separator
  */
 public static void runInstrumentation(
     @NonNull InstrumenterConfigurer configurer,
     @NonNull Directory processDirectory,
     @NonNull String extraPath)
     throws Exception {
   ClassPool classPool = new ClassPool(true);
   classPool.appendPathList(extraPath);
   classPool.appendClassPath(processDirectory.getAbsolutePath());
   InstrumenterImpl instrumenter = new InstrumenterImpl(classPool);
   configurer.configureInstrumenter(instrumenter);
   instrumenter.ensureConfigured();
   new InstrumentationContext(instrumenter, processDirectory, classPool).doInstrument();
 }
 private void doInstrument() throws Exception {
   for (File classfile : processDirectory.getRecurseFileStream().filter(suffix(".class")))
     processAndWriteClass(processDirectory, classfile);
 }
 private void processAndWriteClass(Directory baseDir, File classfile) throws Exception {
   CtClass clazz = classPool.get(ClassNames.getClassName(baseDir, classfile));
   classInstrumenter.instrumentClass(clazz);
   if (clazz.isModified()) clazz.writeFile(processDirectory.getAbsolutePath());
   clazz.detach();
 }