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; }
// passed app to be used to resolve default name and description public DefaultAppConfigurer(Application app) { this.name = app.getClass().getSimpleName(); this.description = ""; }