/*
 * Copyright 2011 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.web.bindery.requestfactory.server;

import com.google.gwt.dev.asm.AnnotationVisitor;
import com.google.gwt.dev.asm.Attribute;
import com.google.gwt.dev.asm.ClassAdapter;
import com.google.gwt.dev.asm.ClassReader;
import com.google.gwt.dev.asm.ClassVisitor;
import com.google.gwt.dev.asm.ClassWriter;
import com.google.gwt.dev.asm.FieldVisitor;
import com.google.gwt.dev.asm.Label;
import com.google.gwt.dev.asm.MethodAdapter;
import com.google.gwt.dev.asm.MethodVisitor;
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.commons.Method;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Util;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.apt.RfApt;
import com.google.web.bindery.requestfactory.server.RequestFactoryInterfaceValidator.ClassLoaderLoader;
import com.google.web.bindery.requestfactory.server.RequestFactoryInterfaceValidator.ErrorContext;
import com.google.web.bindery.requestfactory.server.RequestFactoryInterfaceValidator.Loader;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.DefaultProxyStore;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyChange;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.InstanceRequest;
import com.google.web.bindery.requestfactory.shared.JsonRpcContent;
import com.google.web.bindery.requestfactory.shared.JsonRpcProxy;
import com.google.web.bindery.requestfactory.shared.JsonRpcService;
import com.google.web.bindery.requestfactory.shared.JsonRpcWireName;
import com.google.web.bindery.requestfactory.shared.Locator;
import com.google.web.bindery.requestfactory.shared.LoggingRequest;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.ProxyForName;
import com.google.web.bindery.requestfactory.shared.ProxySerializer;
import com.google.web.bindery.requestfactory.shared.ProxyStore;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.RequestTransport;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ServiceLocator;
import com.google.web.bindery.requestfactory.shared.ServiceName;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
import com.google.web.bindery.requestfactory.shared.WriteOperation;
import com.google.web.bindery.requestfactory.vm.RequestFactorySource;
import com.google.web.bindery.requestfactory.vm.impl.TypeTokenResolver;
import com.google.web.bindery.requestfactory.vm.testing.UrlRequestTransport;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;

import javax.annotation.processing.Processor;

/**
 * Used to extract RequestFactory client jars from {@code gwt-user.jar}.
 */
public class RequestFactoryJarExtractor {
  /*
   * The FooProcessor types are ASM visitors that traverse the bytecode, calling
   * one of the various processFoo() methods. The visitors will also update the
   * bytecode with the rebased type names that are returned from the
   * processFoo() methods.
   */

  /**
   * Describes a way to emit the contents of a classpath, typically into a JAR
   * or filesystem directory.
   */
  public interface Emitter {
    void close() throws IOException;

    void emit(String path, InputStream contents) throws IOException;
  }

  /**
   * An Emitter implementation that creates a jar file.
   */
  public static class JarEmitter implements Emitter {
    private int rawByteSize;
    private final JarOutputStream out;

    public JarEmitter(File outFile) throws IOException {
      Manifest m = new Manifest();
      m.getMainAttributes().putValue("Created-By",
          RequestFactoryJarExtractor.class.getCanonicalName());
      m.getMainAttributes();
      out = new JarOutputStream(new FileOutputStream(outFile), m);
    }

    public void close() throws IOException {
      out.close();
    }

    public void emit(String path, InputStream contents) throws IOException {
      ZipEntry entry = new ZipEntry(path);
      out.putNextEntry(entry);
      byte[] bytes = new byte[4096];
      int read;
      for (;;) {
        read = contents.read(bytes);
        if (read == -1) {
          break;
        }
        rawByteSize += read;
        out.write(bytes, 0, read);
      }
      out.closeEntry();
    }
  }

  /**
   * Controls what is emitted by the tool.
   */
  public enum Mode {
    BOTH(true, true) {
      @Override
      protected boolean matches(String target) {
        return target.endsWith(CODE_AND_SOURCE);
      }
    },
    SOURCE(false, true) {
      @Override
      protected boolean matches(String target) {
        return target.endsWith(SOURCE_ONLY);
      }
    },
    // Order is important, must be last
    CLASSES(true, false) {
      @Override
      protected boolean matches(String target) {
        return true;
      }
    };

    public static Mode match(String target) {
      for (Mode mode : Mode.values()) {
        if (mode.matches(target)) {
          return mode;
        }
      }
      return null;
    }

    private final boolean emitClasses;
    private final boolean emitSource;

    private Mode(boolean emitClasses, boolean emitSource) {
      this.emitClasses = emitClasses;
      this.emitSource = emitSource;
    }

    public boolean isEmitClasses() {
      return emitClasses;
    }

    public boolean isEmitSource() {
      return emitSource;
    }

    protected abstract boolean matches(String target);
  }

  private class AnnotationProcessor implements AnnotationVisitor {
    private final String sourceType;
    private final AnnotationVisitor av;

    public AnnotationProcessor(String sourceType, AnnotationVisitor av) {
      this.sourceType = sourceType;
      this.av = av;
    }

    public void visit(String name, Object value) {
      value = processConstant(sourceType, value);
      av.visit(name, value);
    }

    public AnnotationVisitor visitAnnotation(String name, String desc) {
      desc = processDescriptor(sourceType, desc);
      return new AnnotationProcessor(desc, av.visitAnnotation(name, desc));
    }

    public AnnotationVisitor visitArray(String name) {
      return new AnnotationProcessor(name, av.visitArray(name));
    }

    public void visitEnd() {
      av.visitEnd();
    }

    public void visitEnum(String name, String desc, String value) {
      desc = processDescriptor(sourceType, desc);
      av.visitEnum(name, desc, value);
    }
  }

  private class ClassProcessor extends ClassAdapter {
    private State state;
    private String sourceType;

    public ClassProcessor(String sourceType, ClassVisitor cv, State state) {
      super(cv);
      this.sourceType = sourceType;
      this.state = state;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName,
        String[] interfaces) {
      name = processInternalName(sourceType, name);
      superName = processInternalName(sourceType, superName);
      if (interfaces != null) {
        for (int i = 0, j = interfaces.length; i < j; i++) {
          interfaces[i] = processInternalName(sourceType, interfaces[i]);
        }
      }
      super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      desc = processDescriptor(sourceType, desc);
      return new AnnotationProcessor(sourceType, super.visitAnnotation(desc, visible));
    }

    @Override
    public FieldVisitor visitField(int access, String name, String desc, String signature,
        Object value) {
      desc = processDescriptor(sourceType, desc);
      return new FieldProcessor(sourceType, super.visitField(access, name, desc, signature, value));
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
      name = processInternalName(sourceType, name);
      outerName = processInternalName(sourceType, outerName);
      super.visitInnerClass(name, outerName, innerName, access);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
        String[] exceptions) {
      Method method = processMethod(sourceType, name, desc);
      desc = method.getDescriptor();
      if (exceptions != null) {
        for (int i = 0, j = exceptions.length; i < j; i++) {
          exceptions[i] = processInternalName(sourceType, exceptions[i]);
        }
      }
      MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
      if (mv != null) {
        mv = new MethodProcessor(sourceType, mv);
      }
      return mv;
    }

    @Override
    public void visitOuterClass(String owner, String name, String desc) {
      owner = processInternalName(sourceType, owner);
      if (desc != null) {
        desc = processMethod(sourceType, name, desc).getDescriptor();
      }
      super.visitOuterClass(owner, name, desc);
    }

    @Override
    public void visitSource(String source, String debug) {
      if (source != null) {
        state.source = source;
      }
      super.visitSource(source, debug);
    }
  }

  private class EmitOneResource implements Callable<Void> {
    private final byte[] contents;
    private final String path;

    private EmitOneResource(String path, byte[] contents) {
      this.path = path;
      this.contents = contents;
    }

    @Override
    public Void call() throws Exception {
      if (mode.isEmitClasses()) {
        emitter.emit(path, new ByteArrayInputStream(contents));
      }
      return null;
    }
  }

  /**
   * A unit of work to write one class and its source file into the Emitter.
   */
  private class EmitOneType implements Callable<Void> {
    private final State state;

    /**
     * @param state
     */
    private EmitOneType(State state) {
      this.state = state;
    }

    public Void call() throws Exception {
      if (mode.isEmitClasses()) {
        String fileName = state.type.getInternalName();
        if (fileName == null) {
          System.err.println("Got null filename from " + state.type);
          return null;
        }
        fileName += ".class";
        emitter.emit(fileName, state.contents);
      }
      if (mode.isEmitSource()) {
        String sourcePath = getPackagePath(state.originalType) + state.source;
        String destPath = getPackagePath(state.type) + state.source;
        if (sources.add(sourcePath) && loader.exists(sourcePath)) {
          String contents = Util.readStreamAsString(loader.getResourceAsStream(sourcePath));
          emitter.emit(destPath, new ByteArrayInputStream(Util.getBytes(contents)));
        }
      }
      return null;
    }
  }

  // There is no FieldAdapter type
  private class FieldProcessor implements FieldVisitor {
    private final String sourceType;
    private final FieldVisitor fv;

    public FieldProcessor(String sourceType, FieldVisitor fv) {
      this.sourceType = sourceType;
      this.fv = fv;
    }

    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      return new AnnotationProcessor(sourceType, fv.visitAnnotation(desc, visible));
    }

    public void visitAttribute(Attribute attr) {
      fv.visitAttribute(attr);
    }

    public void visitEnd() {
      fv.visitEnd();
    }
  }

  private class MethodProcessor extends MethodAdapter {
    private final String sourceType;

    public MethodProcessor(String sourceType, MethodVisitor mv) {
      super(mv);
      this.sourceType = sourceType;
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      desc = processDescriptor(sourceType, desc);
      return super.visitAnnotation(desc, visible);
    }

    @Override
    public AnnotationVisitor visitAnnotationDefault() {
      return new AnnotationProcessor(sourceType, super.visitAnnotationDefault());
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
      owner = processInternalName(sourceType, owner);
      desc = processDescriptor(sourceType, desc);
      super.visitFieldInsn(opcode, owner, name, desc);
    }

    @Override
    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
      for (int i = 0, j = local.length; i < j; i++) {
        if (local[i] instanceof String) {
          local[i] = processInternalName(sourceType, (String) local[i]);
        }
      }
      for (int i = 0, j = stack.length; i < j; i++) {
        if (stack[i] instanceof String) {
          stack[i] = processInternalName(sourceType, (String) stack[i]);
        }
      }
      super.visitFrame(type, nLocal, local, nStack, stack);
    }

    @Override
    public void visitLdcInsn(Object cst) {
      cst = processConstant(sourceType, cst);
      super.visitLdcInsn(cst);
    }

    @Override
    public void visitLocalVariable(String name, String desc, String signature, Label start,
        Label end, int index) {
      desc = processDescriptor(sourceType, desc);
      super.visitLocalVariable(name, desc, signature, start, end, index);
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
      owner = processInternalName(sourceType, owner);
      desc = processMethod(sourceType, name, desc).getDescriptor();
      super.visitMethodInsn(opcode, owner, name, desc);
    }

    @Override
    public void visitMultiANewArrayInsn(String desc, int dims) {
      desc = processDescriptor(sourceType, desc);
      super.visitMultiANewArrayInsn(desc, dims);
    }

    @Override
    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
      desc = processDescriptor(sourceType, desc);
      return super.visitParameterAnnotation(parameter, desc, visible);
    }

    @Override
    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
      type = processInternalName(sourceType, type);
      super.visitTryCatchBlock(start, end, handler, type);
    }

    @Override
    public void visitTypeInsn(int opcode, String type) {
      type = processInternalName(sourceType, type);
      super.visitTypeInsn(opcode, type);
    }
  }

  /**
   * Replaces native methods with stub implementations that throw an exception.
   * This allows any dangling GWT types to be loaded by a JVM without triggering
   * an {@link UnsatisfiedLinkError}.
   */
  private class NativeMethodDefanger extends ClassAdapter {
    public NativeMethodDefanger(ClassVisitor cv) {
      super(cv);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
        String[] exceptions) {
      if ((access & Opcodes.ACC_NATIVE) != 0) {
        MethodVisitor mv =
            super.visitMethod(access & ~Opcodes.ACC_NATIVE, name, desc, signature, exceptions);
        if (mv != null) {
          mv.visitCode();
          String exceptionName = Type.getInternalName(RuntimeException.class);
          // <empty>
          mv.visitTypeInsn(Opcodes.NEW, exceptionName);
          // obj
          mv.visitInsn(Opcodes.DUP);
          // obj, obj
          mv.visitLdcInsn(NATIVE_METHOD_ERROR);
          // obj, obj, string
          mv.visitMethodInsn(Opcodes.INVOKESPECIAL, exceptionName, "<init>",
              "(Ljava/lang/String;)V");
          // obj
          mv.visitInsn(Opcodes.ATHROW);

          // Count argument slots - long and double arguments each take up 2
          // slots
          int numSlots = 0;
          for (Type t : Type.getArgumentTypes(desc)) {
            numSlots += t.getSize();
          }
          if ((access & Opcodes.ACC_STATIC) == 0) {
            // Add one for 'this' reference
            numSlots++;
          }
          mv.visitMaxs(3, numSlots);
          mv.visitEnd();
        }
        return null;
      } else {
        return super.visitMethod(access, name, desc, signature, exceptions);
      }
    }
  }

  /**
   * This is the main bytecode-processing entry point. It will read in one
   * classfile and produce a mutated copy. Any referenced types will be enqueued
   * via {@link RequestFactoryJarExtractor#processType(String, Type)}.
   */
  private class ProcessOneType implements Callable<State> {

    private final State state;
    private final String typeName;

    public ProcessOneType(Type type) {
      state = new State(type);
      typeName = type.getClassName();
    }

    public State call() {
      ClassWriter writer = new ClassWriter(0);
      ClassVisitor cv = writer;
      cv = new ClassProcessor(typeName, cv, state);
      cv = new NativeMethodDefanger(cv);
      visit(logger.setType(state.type), loader, state.type.getInternalName(), cv);
      state.contents = new ByteArrayInputStream(writer.toByteArray());
      assert seen.containsKey(state.originalType) : "No type for " + state.type.getClassName();
      state.type = seen.get(state.originalType);

      emit(state);
      return state;
    }
  }

  /**
   * Metadata about a single type.
   */
  private static class State {
    boolean containsNativeMethods;
    /**
     * Will contain the data to be written to disk, possibly mutated class data.
     */
    InputStream contents;
    String source;
    /**
     * The possibly rebased type name.
     */
    Type type;
    final Type originalType;

    public State(Type type) {
      this.originalType = this.type = type;
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder();
      sb.append(type.getInternalName());
      if (containsNativeMethods) {
        sb.append(" NATIVE");
      }
      if (source != null) {
        sb.append(" ").append(source);
      }
      return sb.toString();
    }
  }

  /**
   * If true, print a trace of dependencies to System.out.
   */
  private static final boolean VERBOSE = false;

  /**
   * 
   */
  private static final String CODE_AND_SOURCE = "+src";

  /**
   * 
   */
  private static final String SOURCE_ONLY = "-src";

  private static final String NATIVE_METHOD_ERROR = "Cannot call native method";

  /**
   * A map of target names to the types that target should use as a base.
   */
  private static final Map<String, List<Class<?>>> SEEDS =
      new LinkedHashMap<String, List<Class<?>>>();

  /**
   * Server public API classes and interfaces.
   */
  private static final Class<?>[] SERVER_CLASSES = {
      DefaultExceptionHandler.class, ExceptionHandler.class, Logging.class, LoggingRequest.class,
      RequestFactoryServlet.class, ServiceLayer.class, ServiceLayerDecorator.class,
      SimpleRequestProcessor.class};

  /**
   * Shared public API classes and interfaces.
   */
  @SuppressWarnings("deprecation")
  private static final Class<?>[] SHARED_CLASSES = {
      BaseProxy.class, DefaultProxyStore.class, EntityProxy.class, EntityProxyChange.class,
      EntityProxyId.class, InstanceRequest.class, JsonRpcContent.class, JsonRpcProxy.class,
      JsonRpcService.class, JsonRpcWireName.class, Locator.class, ProxyFor.class,
      ProxyForName.class, ProxySerializer.class, ProxyStore.class, Receiver.class, Request.class,
      RequestContext.class, RequestFactory.class, RequestTransport.class, ServerFailure.class,
      Service.class, ServiceLocator.class, ServiceName.class, ValueProxy.class,
      com.google.web.bindery.requestfactory.shared.Violation.class, WriteOperation.class,
      RequestFactorySource.class, SimpleEventBus.class};

  /**
   * Maximum number of threads to use to run the Extractor.
   */
  private static final int MAX_THREADS = 4;

  static {
    List<Class<?>> sharedClasses = Arrays.<Class<?>> asList(SHARED_CLASSES);

    List<Class<?>> clientClasses = new ArrayList<Class<?>>();
    clientClasses.addAll(sharedClasses);
    clientClasses.add(RfApt.class);
    clientClasses.add(UrlRequestTransport.class);

    List<Class<?>> serverClasses = new ArrayList<Class<?>>();
    serverClasses.addAll(Arrays.<Class<?>> asList(SERVER_CLASSES));
    serverClasses.addAll(sharedClasses);

    SEEDS.put("apt", Collections.unmodifiableList(Arrays.<Class<?>> asList(RfApt.class)));
    SEEDS.put("client", Collections.unmodifiableList(clientClasses));
    SEEDS.put("server", Collections.unmodifiableList(serverClasses));

    Set<Class<?>> all = new LinkedHashSet<Class<?>>();
    for (List<Class<?>> value : SEEDS.values()) {
      all.addAll(value);
    }
    SEEDS.put("all", Collections.unmodifiableList(new ArrayList<Class<?>>(all)));

    for (String target : new ArrayList<String>(SEEDS.keySet())) {
      SEEDS.put(target + SOURCE_ONLY, SEEDS.get(target));
      SEEDS.put(target + CODE_AND_SOURCE, SEEDS.get(target));
    }

    /*
     * Allows the rebased package to be tested. This is done with a by-name
     * lookup, since the gwt-user code is compiled separately from its tests.
     */
    try {
      SEEDS.put("test" + CODE_AND_SOURCE, Collections.unmodifiableList(Arrays.<Class<?>> asList(
          Class.forName("com.google.web.bindery.requestfactory.vm.RequestFactoryJreSuite"), Class
              .forName("com.google.web.bindery.requestfactory.server.SimpleBar"))));
    } catch (ClassNotFoundException ignored) {
    }
  }

  public static void main(String[] args) throws IOException {
    if (args.length < 2) {
      System.err.println("Usage: java -cp gwt-dev.jar:gwt-user.jar:json.jar"
          + RequestFactoryJarExtractor.class.getCanonicalName() + " <target-name> outfile.jar");
      System.err.println("Valid targets:");
      for (String target : SEEDS.keySet()) {
        System.err.println("  " + target);
      }
      System.exit(1);
    }
    String target = args[0];
    List<Class<?>> seeds = SEEDS.get(target);
    if (seeds == null) {
      System.err.println("Unknown target: " + target);
      System.exit(1);
    }
    Map<String, byte[]> resources = createResources(target, seeds);
    Mode mode = Mode.match(target);
    Logger errorContext = Logger.getLogger(RequestFactoryJarExtractor.class.getName());
    ClassLoaderLoader classLoader =
        new ClassLoaderLoader(Thread.currentThread().getContextClassLoader());
    JarEmitter jarEmitter = new JarEmitter(new File(args[1]));
    RequestFactoryJarExtractor extractor =
        new RequestFactoryJarExtractor(errorContext, classLoader, jarEmitter, seeds, resources,
            mode);
    extractor.run();
    System.exit(extractor.isExecutionFailed() ? 1 : 0);
  }

  private static Map<String, byte[]> createResources(String target, List<Class<?>> seeds)
      throws UnsupportedEncodingException, IOException {
    Map<String, byte[]> resources;
    if (seeds.contains(RfApt.class)) {
      // Add the annotation processor manifest
      resources =
          Collections.singletonMap("META-INF/services/" + Processor.class.getCanonicalName(),
              RfApt.class.getCanonicalName().getBytes("UTF-8"));
    } else if (("test" + CODE_AND_SOURCE).equals(target)) {
      // Combine all type token maps to run tests
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      TypeTokenResolver resolver = TypeTokenResolver.loadFromClasspath();
      resolver.store(out);
      resources = Collections.singletonMap(TypeTokenResolver.TOKEN_MANIFEST, out.toByteArray());
    } else {
      resources = Collections.emptyMap();
    }
    return resources;
  }

  /**
   * Given a Type, return a path-prefix based on the type's package.
   */
  private static String getPackagePath(Type t) {
    String name = t.getInternalName();
    return name.substring(0, name.lastIndexOf('/') + 1);
  }

  /**
   * Load the classfile for the given binary name and apply the provided
   * visitor.
   * 
   * @return <code>true</code> if the visitor was successfully visited
   */
  private static boolean visit(ErrorContext logger, Loader loader, String internalName,
      ClassVisitor visitor) {
    assert Name.isInternalName(internalName) : "internalName";
    logger.spam("Visiting " + internalName);
    InputStream inputStream = null;
    try {
      inputStream = loader.getResourceAsStream(internalName + ".class");
      if (inputStream == null) {
        System.err.println("Could not find class file for " + internalName);
        logger.poison("Could not find class file for " + internalName);
        return false;
      }
      ClassReader reader = new ClassReader(inputStream);
      reader.accept(visitor, 0);
      return true;
    } catch (IOException e) {
      logger.poison("Unable to open " + internalName, e);
    } finally {
      if (inputStream != null) {
        try {
          inputStream.close();
        } catch (IOException ignored) {
        }
      }
    }
    return false;
  }

  private boolean executionFailed = false;
  private final Emitter emitter;
  private final ExecutorService ex;
  private final BlockingQueue<Future<?>> inProcess = new LinkedBlockingQueue<Future<?>>();
  private final ErrorContext logger;
  private final Loader loader;
  private final Mode mode;
  private final Map<String, byte[]> resources;
  private final List<Class<?>> seeds;
  private final Map<Type, Type> seen = new ConcurrentHashMap<Type, Type>();
  private final Set<String> sources = new ConcurrentSkipListSet<String>();
  private final ExecutorService writerService;

  public RequestFactoryJarExtractor(Logger logger, Loader loader, Emitter emitter,
      List<Class<?>> seeds, Map<String, byte[]> resources, Mode mode) {
    this.logger = new ErrorContext(logger);
    this.loader = loader;
    this.emitter = emitter;
    this.resources = resources;
    this.seeds = seeds;
    this.mode = mode;

    int numThreads = Math.min(MAX_THREADS, Runtime.getRuntime().availableProcessors());
    ex = Executors.newFixedThreadPool(numThreads);
    writerService = Executors.newSingleThreadExecutor();
  }

  /**
   * Blocks until all work has been finished.
   */
  public void run() throws IOException {
    for (Class<?> seed : seeds) {
      processType("seeds", Type.getType(seed));
    }
    for (Map.Entry<String, byte[]> entry : resources.entrySet()) {
      writerService.submit(new EmitOneResource(entry.getKey(), entry.getValue()));
    }
    // Wait for all tasks to be completed
    while (!inProcess.isEmpty()) {
      try {
        Future<?> task = inProcess.take();
        task.get();
      } catch (InterruptedException retry) {
      } catch (ExecutionException e) {
        e.getCause().printStackTrace();
        executionFailed = true;
      }
    }
    emitter.close();
  }

  /**
   * Write one type into the output.
   */
  private void emit(final State state) {
    inProcess.add(writerService.submit(new EmitOneType(state)));
  }

  private boolean isExecutionFailed() {
    return executionFailed;
  }

  /**
   * Look at constant values from the bytecode, processing referenced types.
   */
  private Object processConstant(String sourceType, Object value) {
    if (value instanceof Type) {
      value = processType(sourceType, (Type) value);
    }
    return value;
  }

  /**
   * Process the type represented by the descriptor, possibly returning a
   * rebased descriptor.
   */
  private String processDescriptor(String sourceType, String desc) {
    if (desc == null) {
      return null;
    }
    return processType(sourceType, Type.getType(desc)).getDescriptor();
  }

  /**
   * Process the type represented by the name, possibly returning a rebased
   * name.
   */
  private String processInternalName(String sourceType, String internalName) {
    if (internalName == null) {
      return null;
    }
    return processType(sourceType, Type.getObjectType(internalName)).getInternalName();
  }

  /**
   * Produce a rebased method declaration, also visiting referenced types.
   */
  private Method processMethod(String sourceType, String name, String desc) {
    Method method = new Method(name, desc);
    Type[] argumentTypes = method.getArgumentTypes();
    for (int i = 0, j = argumentTypes.length; i < j; i++) {
      argumentTypes[i] = processType(sourceType, argumentTypes[i]);
    }
    method = new Method(name, processType(sourceType, method.getReturnType()), argumentTypes);
    return method;
  }

  /**
   * Process a type, possibly returning a rebased type.
   * 
   * @param sourceType TODO
   */
  private Type processType(String sourceType, Type type) {
    Type toReturn;
    synchronized (seen) {
      toReturn = seen.get(type);
      if (toReturn != null) {
        return toReturn;
      }
      toReturn = Type.getType(type.getDescriptor());
      seen.put(type, toReturn);
    }
    int sort = type.getSort();
    if (sort != Type.OBJECT && sort != Type.ARRAY) {
      return toReturn;
    }
    if (sort == Type.ARRAY) {
      processType(sourceType, type.getElementType());
      return toReturn;
    }
    assert type.getInternalName().charAt(0) != 'L';
    if (type.getInternalName().startsWith("java/") || type.getInternalName().startsWith("javax/")) {
      return toReturn;
    }
    if (VERBOSE) {
      System.out.println(sourceType + " -> " + type.getClassName());
    }
    Future<State> future = ex.submit(new ProcessOneType(type));
    inProcess.add(future);
    return toReturn;
  }
}
