static {
    ClassScanner.setReflectionsScanning(true);

    ParserFactory.registerParser(
        new Parser() {
          @Override
          public EJValue parse(final String input) {
            return JSONDecoder.decode(input);
          }
        });

    ServerMappingContext sContext;

    try {
      if (!MarshallingGenUtil.isUseStaticMarshallers()) {
        sContext = loadDynamicMarshallers();
      } else {
        try {
          sContext = loadPrecompiledMarshallers();
        } catch (Throwable t) {
          log.debug("failed to load static marshallers", t);
          log.warn("static marshallers were not found.");

          if (MarshallingGenUtil.isForceStaticMarshallers()) {
            throw new IOException(
                "Enforcing static marshallers but failed to load generated server marshallers", t);
          }

          sContext = loadDynamicMarshallers();
        } finally {
          ClassScanner.setReflectionsScanning(false);
        }
      }
    } catch (Throwable t) {
      t.printStackTrace();
      log.error(t.getMessage());
      throw new RuntimeException("critical problem loading the marshallers", t);
    }

    context = sContext;
  }
  private void arrayDemarshallCode(
      MetaClass toMap, int dim, AnonymousClassStructureBuilder anonBuilder) {
    Object[] dimParms = new Object[dim];
    dimParms[0] = Stmt.loadVariable("a0").invoke("size");

    final MetaClass arrayType = toMap.asArrayOf(dim);

    MetaClass outerType = toMap.getOuterComponentType();
    if (!outerType.isArray() && outerType.isPrimitive()) {
      outerType = outerType.asBoxed();
    }

    Statement outerAccessorStatement =
        loadVariable("newArray", loadVariable("i"))
            .assignValue(Cast.to(outerType, loadVariable("a0").invoke("get", loadVariable("i"))));

    //    /**
    //     * Special case for handling char elements.
    //     */
    //    if (outerType.getFullyQualifiedName().equals(Character.class.getName())) {
    //      outerAccessorStatement =
    //              loadVariable("newArray", loadVariable("i"))
    //                      .assignValue(
    //                              Stmt.nestedCall(Cast.to(String.class,
    // loadVariable("a0").invoke("get", loadVariable("i"))))
    //                                      .invoke("charAt", 0));
    //    }

    final BlockBuilder<?> dmBuilder =
        anonBuilder
            .privateMethod(arrayType, "_demarshall" + dim)
            .parameters(List.class, MarshallingSession.class)
            .body();

    dmBuilder.append(
        Stmt.declareVariable(arrayType)
            .named("newArray")
            .initializeWith(Stmt.newArray(toMap, dimParms)));

    dmBuilder
        .append(
            autoForLoop("i", Stmt.loadVariable("newArray").loadField("length"))
                .append(
                    dim == 1
                        ? outerAccessorStatement
                        : loadVariable("newArray", loadVariable("i"))
                            .assignValue(
                                Stmt.invokeStatic(
                                    anonBuilder.getClassDefinition(),
                                    "_demarshall" + (dim - 1),
                                    Cast.to(
                                        List.class,
                                        Stmt.loadVariable("a0")
                                            .invoke("get", Stmt.loadVariable("i"))),
                                    Stmt.loadVariable("a1"))))
                .finish())
        .append(Stmt.loadVariable("newArray").returnValue());

    dmBuilder.finish();

    final BlockBuilder<?> mBuilder =
        anonBuilder
            .privateMethod(String.class, "_marshall" + dim)
            .parameters(arrayType, MarshallingSession.class)
            .body();

    mBuilder
        .append(
            Stmt.declareVariable(StringBuilder.class)
                .named("sb")
                .initializeWith(Stmt.newObject(StringBuilder.class).withParameters("[")))
        .append(
            autoForLoop("i", Stmt.loadVariable("a0").loadField("length"))
                .append(
                    Stmt.if_(Bool.greaterThan(Stmt.loadVariable("i"), 0))
                        .append(Stmt.loadVariable("sb").invoke("append", ","))
                        .finish())
                .append(
                    Stmt.loadVariable("sb")
                        .invoke(
                            "append",
                            dim == 1
                                ? Stmt.loadVariable(MarshallingGenUtil.getVarName(outerType))
                                    .invoke(
                                        "marshall",
                                        Stmt.loadVariable("a0", Stmt.loadVariable("i")),
                                        Stmt.loadVariable("a1"))
                                : Stmt.invokeStatic(
                                    anonBuilder.getClassDefinition(),
                                    "_marshall" + (dim - 1),
                                    Stmt.loadVariable("a0", Stmt.loadVariable("i")),
                                    loadVariable("a1"))))
                .finish())
        .append(Stmt.loadVariable("sb").invoke("append", "]").invoke("toString").returnValue())
        .finish();

    if (dim > 1) {
      arrayDemarshallCode(toMap, dim - 1, anonBuilder);
    }
  }
Beispiel #3
0
  public static Class<? extends MarshallerFactory> getGeneratedMarshallerFactoryForServer() {
    final String packageName = MarshallersGenerator.SERVER_MARSHALLER_PACKAGE_NAME;
    final String className = MarshallersGenerator.SERVER_MARSHALLER_CLASS_NAME;

    try {
      log.debug("searching for marshaller class: " + packageName + "." + className);

      final String classResource = packageName.replaceAll("\\.", "/") + "/" + className + ".class";
      final Set<String> locations = new HashSet<String>();

      // look for the class in every classloader we can think of. For example, current thread
      // classloading works in Jetty but not JBoss AS 7.
      locations.addAll(
          urlToFile(Thread.currentThread().getContextClassLoader().getResources(classResource)));
      locations.addAll(
          urlToFile(ServerMarshallUtil.class.getClassLoader().getResources(classResource)));
      locations.addAll(urlToFile(ClassLoader.getSystemResources(classResource)));

      File newest = null;
      for (String url : locations) {
        final File file = ClassChangeUtil.getFileIfExists(url);
        if (file != null && (newest == null || file.lastModified() > newest.lastModified())) {
          newest = file;
        }
      }

      if (locations.size() > 1) {
        log.warn(
            "*** MULTIPLE VERSIONS OF "
                + packageName
                + "."
                + className
                + " FOUND IN CLASSPATH: "
                + "Attempted to guess the newest one based on file dates. But you should clean your output directories");

        for (String loc : locations) {
          log.warn(" Ambiguous version -> " + loc);
        }
      }

      if (newest == null) {
        try {
          // maybe we're in an appserver with a VFS, so try to load anyways.
          return Thread.currentThread()
              .getContextClassLoader()
              .loadClass(packageName + "." + className)
              .asSubclass(MarshallerFactory.class);
        } catch (ClassNotFoundException e) {
          log.warn("could not locate marshaller class.");
          if (!MarshallingGenUtil.isForceStaticMarshallers()) {
            return null;
          } else {
            log.info("couldn't find marshaller class, attempting to generate ...");
          }
        }
      } else {
        return ClassChangeUtil.loadClassDefinition(
            newest.getAbsolutePath(), packageName, className);
      }
    } catch (IOException e) {
      e.printStackTrace();
      log.warn("could not read marshaller classes: " + e);
    }

    final String classStr =
        MarshallerGeneratorFactory.getFor(MarshallerOutputTarget.Java)
            .generate(packageName, className);

    final File directory =
        new File(
            RebindUtils.getTempDirectory()
                + "/errai.gen/classes/"
                + packageName.replaceAll("\\.", "/"));

    final File sourceFile =
        new File(directory.getAbsolutePath() + File.separator + className + ".java");

    try {
      if (directory.exists()) {
        for (File file : directory.listFiles()) {
          file.delete();
        }

        directory.delete();
      }

      directory.mkdirs();

      final FileOutputStream outputStream = new FileOutputStream(sourceFile);

      outputStream.write(classStr.getBytes("UTF-8"));
      outputStream.flush();
      outputStream.close();

      String compiledClassPath =
          ClassChangeUtil.compileClass(
              directory.getAbsolutePath(), packageName, className, directory.getAbsolutePath());

      return ClassChangeUtil.loadClassDefinition(compiledClassPath, packageName, className);
    } catch (IOException e) {
      throw new RuntimeException("failed to generate class ", e);
    }
  }
  private void appendPageShowMethod(
      AnonymousClassStructureBuilder pageImplBuilder,
      MetaClass pageClass,
      Class<? extends Annotation> annotation,
      boolean addPrivateAccessors) {
    BlockBuilder<?> method =
        pageImplBuilder
            .publicMethod(
                void.class,
                createMethodNameFromAnnotation(annotation),
                Parameter.of(pageClass, "widget"),
                Parameter.of(HistoryToken.class, "state"))
            .body();

    int idx = 0;

    method.append(Stmt.declareFinalVariable("pageState", Map.class, new HashMap<String, Object>()));
    for (MetaField field : pageClass.getFieldsAnnotatedWith(PageState.class)) {
      PageState psAnno = field.getAnnotation(PageState.class);
      String fieldName = field.getName();
      String queryParamName = psAnno.value();
      if (queryParamName == null || queryParamName.trim().isEmpty()) {
        queryParamName = fieldName;
      }

      if (addPrivateAccessors) {
        PrivateAccessUtil.addPrivateAccessStubs(
            PrivateAccessType.Write, "jsni", pageImplBuilder, field, new Modifier[] {});
      }

      String injectorName = PrivateAccessUtil.getPrivateFieldInjectorName(field);

      MetaClass erasedFieldType = field.getType().getErased();
      if (erasedFieldType.isAssignableTo(Collection.class)) {
        MetaClass elementType =
            MarshallingGenUtil.getConcreteCollectionElementType(field.getType());
        if (elementType == null) {
          throw new UnsupportedOperationException(
              "Found a @PageState field with a Collection type but without a concrete type parameter. "
                  + "Collection-typed @PageState fields must specify a concrete type parameter.");
        }
        if (erasedFieldType.equals(MetaClassFactory.get(Set.class))) {
          method.append(Stmt.declareVariable(fieldName, Stmt.newObject(HashSet.class)));
        } else if (erasedFieldType.equals(MetaClassFactory.get(List.class))
            || erasedFieldType.equals(MetaClassFactory.get(Collection.class))) {
          method.append(Stmt.declareVariable(fieldName, Stmt.newObject(ArrayList.class)));
        } else {
          throw new UnsupportedOperationException(
              "Found a @PageState field which is a collection of type "
                  + erasedFieldType.getFullyQualifiedName()
                  + ". For collection-valued fields, only the exact types java.util.Collection, java.util.Set, and "
                  + "java.util.List are supported at this time.");
        }

        // for (String fv{idx} : state.get({fieldName}))
        method.append(
            Stmt.loadVariable("state")
                .invoke("getState")
                .invoke("get", queryParamName)
                .foreach("elem", Object.class)
                .append(
                    Stmt.declareVariable(
                        "fv" + idx, Stmt.castTo(String.class, Stmt.loadVariable("elem"))))
                .append(
                    Stmt.loadVariable(fieldName)
                        .invoke(
                            "add",
                            paramFromStringStatement(elementType, Stmt.loadVariable("fv" + idx))))
                .append(
                    Stmt.loadVariable("pageState")
                        .invoke("put", fieldName, Stmt.loadVariable(fieldName)))
                .finish());
        method.append(
            Stmt.loadVariable("this")
                .invoke(injectorName, Stmt.loadVariable("widget"), Stmt.loadVariable(fieldName)));
      } else {
        method.append(
            Stmt.declareFinalVariable(
                "fv" + idx,
                Collection.class,
                Stmt.loadVariable("state").invoke("getState").invoke("get", queryParamName)));
        method.append(
            If.cond(
                    Bool.or(
                        Bool.isNull(Stmt.loadVariable("fv" + idx)),
                        Stmt.loadVariable("fv" + idx).invoke("isEmpty")))
                .append(
                    Stmt.loadVariable("this")
                        .invoke(
                            injectorName,
                            Stmt.loadVariable("widget"),
                            defaultValueStatement(erasedFieldType)))
                .finish()
                .else_()
                .append(
                    Stmt.loadVariable("this")
                        .invoke(
                            injectorName,
                            Stmt.loadVariable("widget"),
                            paramFromStringStatement(
                                erasedFieldType,
                                Stmt.loadVariable("fv" + idx).invoke("iterator").invoke("next"))))
                .append(
                    Stmt.loadVariable("pageState")
                        .invoke(
                            "put",
                            fieldName,
                            Stmt.loadVariable("fv" + idx).invoke("iterator").invoke("next")))
                .finish());
      }
      idx++;
    }

    if (addPrivateAccessors) {
      method.append(
          Stmt.invokeStatic(
              CDI.class,
              "fireEvent",
              Stmt.newObject(NavigationEvent.class)
                  .withParameters(
                      Stmt.newObject(PageRequest.class)
                          .withParameters(
                              getPageName(pageClass), Stmt.loadVariable("pageState")))));
    }

    checkMethodAndAddPrivateAccessors(
        pageImplBuilder, method, pageClass, annotation, HistoryToken.class, "state");

    method.finish();
  }