private void loadMarshallers() {
    Set<Class<?>> marshallers =
        ScannerSingleton.getOrCreateInstance().getTypesAnnotatedWith(ClientMarshaller.class);

    for (Class<?> cls : marshallers) {
      if (Marshaller.class.isAssignableFrom(cls)) {
        try {
          Class<?> type =
              (Class<?>) Marshaller.class.getMethod("getTypeHandled").invoke(cls.newInstance());
          mappingContext.registerMarshaller(type.getName(), cls.asSubclass(Marshaller.class));

          if (cls.isAnnotationPresent(ImplementationAliases.class)) {
            for (Class<?> c : cls.getAnnotation(ImplementationAliases.class).value()) {
              mappingContext.registerMappingAlias(c, type);
            }
          }
        } catch (Throwable t) {
          throw new RuntimeException("could not instantiate marshaller class: " + cls.getName(), t);
        }
      } else {
        throw new RuntimeException(
            "class annotated with "
                + ClientMarshaller.class.getCanonicalName()
                + " does not implement "
                + Marshaller.class.getName());
      }
    }
  }
  private String _generate(String packageName, String clazzName) {
    startTime = System.currentTimeMillis();

    classStructureBuilder = implement(MarshallerFactory.class, packageName, clazzName);
    classContext = ((BuildMetaClass) classStructureBuilder.getClassDefinition()).getContext();
    mappingContext =
        new MappingContext(
            classContext,
            classStructureBuilder.getClassDefinition(),
            classStructureBuilder,
            new ArrayMarshallerCallback() {
              @Override
              public Statement marshal(MetaClass type, Statement value) {
                createDemarshallerIfNeeded(type);
                return value;
              }

              @Override
              public Statement demarshall(MetaClass type, Statement value) {
                String variable = createDemarshallerIfNeeded(type);

                value =
                    Stmt.loadVariable(getVarName(List.class))
                        .invoke("demarshall", value, Stmt.loadVariable("a1"));

                return Stmt.loadVariable(variable)
                    .invoke("demarshall", value, Stmt.loadVariable("a1"));
              }

              private String createDemarshallerIfNeeded(MetaClass type) {
                return addArrayMarshaller(type);
              }
            });

    loadMarshallers();

    MetaClass javaUtilMap = MetaClassFactory.get(new TypeLiteral<Map<String, Marshaller>>() {});

    autoInitializedField(classStructureBuilder, javaUtilMap, MARSHALLERS_VAR, HashMap.class);

    constructor = classStructureBuilder.publicConstructor();

    for (Map.Entry<String, Class<? extends Marshaller>> entry :
        mappingContext.getAllMarshallers().entrySet()) {
      String varName = getVarName(entry.getKey());
      String arrayVarName = getArrayVarName(entry.getKey());
      classStructureBuilder.privateField(varName, entry.getValue()).finish();
      classStructureBuilder.privateField(arrayVarName, entry.getValue()).finish();

      constructor.append(
          Stmt.create(classContext)
              .loadVariable(varName)
              .assignValue(Stmt.newObject(entry.getValue())));

      constructor.append(
          Stmt.create(classContext)
              .loadVariable(MARSHALLERS_VAR)
              .invoke("put", entry.getKey(), loadVariable(varName)));

      for (String s : mappingContext.getReverseMappingAliasFor(entry.getKey())) {
        constructor.append(
            Stmt.create(classContext)
                .loadVariable(MARSHALLERS_VAR)
                .invoke("put", s, loadVariable(varName)));
      }
    }

    generateMarshallers();

    classStructureBuilder
        .publicMethod(Marshaller.class, "getMarshaller")
        .parameters(String.class, String.class)
        .body()
        .append(loadVariable(MARSHALLERS_VAR).invoke("get", loadVariable("a1")).returnValue())
        .finish();

    // special support for Object[]
    addArrayMarshaller(MetaClassFactory.get(Object[].class));

    return classStructureBuilder.toJavaString();

    // System.out.println("[Generation Finished in: " + (System.currentTimeMillis() - startTime) +
    // "ms]");

    //  System.out.println(generatedClass);
    // return generatedClass;
  }
  private Statement generateArrayMarshaller(MetaClass arrayType) {
    MetaClass toMap = arrayType;
    while (toMap.isArray()) {
      toMap = toMap.getComponentType();
    }
    int dimensions = GenUtil.getArrayDimensions(arrayType);

    AnonymousClassStructureBuilder classStructureBuilder =
        Stmt.create(mappingContext.getCodegenContext())
            .newObject(parameterizedAs(Marshaller.class, typeParametersOf(List.class, arrayType)))
            .extend();

    MetaClass anonClass = classStructureBuilder.getClassDefinition();

    classStructureBuilder
        .publicOverridesMethod("getTypeHandled")
        .append(Stmt.load(toMap).returnValue())
        .finish();

    classStructureBuilder
        .publicOverridesMethod("getEncodingType")
        .append(Stmt.load("json").returnValue())
        .finish();

    BlockBuilder<?> bBuilder =
        classStructureBuilder.publicOverridesMethod(
            "demarshall",
            Parameter.of(Object.class, "a0"),
            Parameter.of(MarshallingSession.class, "a1"));

    bBuilder.append(
        Stmt.if_(Bool.isNull(loadVariable("a0")))
            .append(Stmt.load(null).returnValue())
            .finish()
            .else_()
            .append(
                Stmt.invokeStatic(
                        anonClass,
                        "_demarshall" + dimensions,
                        loadVariable("a0"),
                        loadVariable("a1"))
                    .returnValue())
            .finish());
    bBuilder.finish();

    arrayDemarshallCode(toMap, dimensions, classStructureBuilder);

    BlockBuilder<?> marshallMethodBlock =
        classStructureBuilder.publicOverridesMethod(
            "marshall",
            Parameter.of(Object.class, "a0"),
            Parameter.of(MarshallingSession.class, "a1"));

    marshallMethodBlock.append(
        Stmt.if_(Bool.isNull(loadVariable("a0")))
            .append(Stmt.load(null).returnValue())
            .finish()
            .else_()
            .append(
                Stmt.invokeStatic(
                        anonClass, "_marshall" + dimensions, loadVariable("a0"), loadVariable("a1"))
                    .returnValue())
            .finish());

    classStructureBuilder
        .publicOverridesMethod("handles", Parameter.of(JSONValue.class, "a0"))
        .append(Stmt.load(true).returnValue())
        .finish();

    marshallMethodBlock.finish();

    return classStructureBuilder.finish();
  }
  private void generateMarshallers() {
    MetaDataScanner scanner = ScannerSingleton.getOrCreateInstance();

    Set<Class<?>> exposed = new HashSet<Class<?>>(scanner.getTypesAnnotatedWith(Portable.class));
    exposed.addAll(scanner.getTypesAnnotatedWith(ExposeEntity.class));

    // add all GWT JRE  classes

    exposed.add(Throwable.class);
    exposed.add(NullPointerException.class);
    exposed.add(RuntimeException.class);
    exposed.add(Exception.class);
    exposed.add(ArithmeticException.class);
    exposed.add(ArrayStoreException.class);
    exposed.add(AssertionError.class);
    exposed.add(ClassCastException.class);
    exposed.add(IllegalArgumentException.class);
    exposed.add(IndexOutOfBoundsException.class);
    exposed.add(NegativeArraySizeException.class);
    exposed.add(NumberFormatException.class);
    exposed.add(StringIndexOutOfBoundsException.class);
    exposed.add(UnsupportedOperationException.class);
    exposed.add(StackTraceElement.class);

    exposed.add(IOException.class);
    exposed.add(UnsupportedEncodingException.class);
    exposed.add(ConcurrentModificationException.class);
    exposed.add(EmptyStackException.class);
    // exposed.add(MissingResourceException.class);
    // exposed.add(NoSuchMethodException.class);

    for (Class<?> clazz : exposed) {
      mappingContext.registerGeneratedMarshaller(clazz.getName());
    }

    for (Class<?> clazz : exposed) {
      if (clazz.isEnum()) continue;

      MetaClass metaClazz = MetaClassFactory.get(clazz);
      Statement marshaller = marshal(metaClazz);
      MetaClass type = marshaller.getType();
      String varName = getVarName(clazz);

      classStructureBuilder.privateField(varName, type).finish();

      constructor.append(loadVariable(varName).assignValue(marshaller));

      constructor.append(
          Stmt.create(classContext)
              .loadVariable(MARSHALLERS_VAR)
              .invoke("put", clazz.getName(), loadVariable(varName)));

      for (String s : mappingContext.getReverseMappingAliasFor(clazz.getName())) {
        constructor.append(
            Stmt.create(classContext)
                .loadVariable(MARSHALLERS_VAR)
                .invoke("put", s, loadVariable(varName)));
      }
    }

    constructor.finish();
  }