Exemplo n.º 1
0
  /** Creates a {@link PluginPropertyField} based on the given field. */
  private PluginPropertyField createPluginProperty(Field field, TypeToken<?> resolvingType)
      throws UnsupportedTypeException {
    TypeToken<?> fieldType = resolvingType.resolveType(field.getGenericType());
    Class<?> rawType = fieldType.getRawType();

    Name nameAnnotation = field.getAnnotation(Name.class);
    Description descAnnotation = field.getAnnotation(Description.class);
    String name = nameAnnotation == null ? field.getName() : nameAnnotation.value();
    String description = descAnnotation == null ? "" : descAnnotation.value();

    if (rawType.isPrimitive()) {
      return new PluginPropertyField(name, description, rawType.getName(), true);
    }

    rawType = Primitives.unwrap(rawType);
    if (!rawType.isPrimitive() && !String.class.equals(rawType)) {
      throw new UnsupportedTypeException("Only primitive and String types are supported");
    }

    boolean required = true;
    for (Annotation annotation : field.getAnnotations()) {
      if (annotation.annotationType().getName().endsWith(".Nullable")) {
        required = false;
        break;
      }
    }

    return new PluginPropertyField(
        name, description, rawType.getSimpleName().toLowerCase(), required);
  }
Exemplo n.º 2
0
  private List<ApplicationClass> inspectApplications(File artifactFile)
      throws IOException, InvalidArtifactException {
    List<ApplicationClass> apps = Lists.newArrayList();

    Location artifactLocation = Locations.toLocation(artifactFile);
    Manifest manifest = BundleJarUtil.getManifest(artifactLocation);
    if (manifest == null) {
      return apps;
    }
    Attributes manifestAttributes = manifest.getMainAttributes();
    if (manifestAttributes == null) {
      return apps;
    }

    // right now we force users to include the application main class as an attribute in their
    // manifest,
    // which forces them to have a single application class.
    // in the future, we may want to let users do this or maybe specify a list of classes or
    // a package that will be searched for applications, to allow multiple applications in a single
    // artifact.
    String mainClassName = manifestAttributes.getValue(ManifestFields.MAIN_CLASS);
    if (mainClassName != null) {
      try (CloseableClassLoader artifactClassLoader =
          artifactClassLoaderFactory.createClassLoader(Locations.toLocation(artifactFile))) {

        Object appMain = artifactClassLoader.loadClass(mainClassName).newInstance();
        if (!(appMain instanceof Application)) {
          throw new InvalidArtifactException(
              String.format(
                  "Application main class is of invalid type: %s", appMain.getClass().getName()));
        }

        Application app = (Application) appMain;

        TypeToken typeToken = TypeToken.of(app.getClass());
        TypeToken<?> resultToken = typeToken.resolveType(Application.class.getTypeParameters()[0]);
        Type configType;
        // if the user parameterized their template, like 'xyz extends ApplicationTemplate<T>',
        // we can deserialize the config into that object. Otherwise it'll just be a Config
        if (resultToken.getType() instanceof Class) {
          configType = resultToken.getType();
        } else {
          configType = Config.class;
        }
        apps.add(new ApplicationClass(mainClassName, "", schemaGenerator.generate(configType)));
      } catch (ClassNotFoundException e) {
        throw new InvalidArtifactException(
            String.format("Could not find Application main class %s.", mainClassName));
      } catch (UnsupportedTypeException e) {
        throw new InvalidArtifactException(
            String.format("Config for Application %s has an unsupported schema.", mainClassName));
      } catch (InstantiationException | IllegalAccessException e) {
        throw new InvalidArtifactException(
            String.format("Could not instantiate Application class %s.", mainClassName), e);
      }
    }
    return apps;
  }