Search in sources :

Example 1 with PluginClass

use of co.cask.cdap.api.plugin.PluginClass in project cdap by caskdata.

the class AppSystemMetadataWriter method getSystemPropertiesToAdd.

@Override
protected Map<String, String> getSystemPropertiesToAdd() {
    ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
    properties.put(ENTITY_NAME_KEY, appSpec.getName());
    properties.put(VERSION_KEY, appId.getVersion());
    String description = appSpec.getDescription();
    if (!Strings.isNullOrEmpty(description)) {
        properties.put(DESCRIPTION_KEY, description);
    }
    if (!existing) {
        properties.put(CREATION_TIME_KEY, String.valueOf(System.currentTimeMillis()));
    }
    addPrograms(properties);
    addSchedules(properties);
    // appSpec.getPlugins() returns all instances of all plugins, so there may be duplicates.
    // we only store unique plugins right now
    Set<PluginClass> existingPluginClasses = new HashSet<>();
    for (Plugin plugin : appSpec.getPlugins().values()) {
        if (!existingPluginClasses.contains(plugin.getPluginClass())) {
            addPlugin(plugin.getPluginClass(), null, properties);
            existingPluginClasses.add(plugin.getPluginClass());
        }
    }
    return properties.build();
}
Also used : PluginClass(co.cask.cdap.api.plugin.PluginClass) ImmutableMap(com.google.common.collect.ImmutableMap) HashSet(java.util.HashSet) Plugin(co.cask.cdap.api.plugin.Plugin)

Example 2 with PluginClass

use of co.cask.cdap.api.plugin.PluginClass in project cdap by caskdata.

the class ArtifactSystemMetadataWriter method getSystemPropertiesToAdd.

@Override
protected Map<String, String> getSystemPropertiesToAdd() {
    ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
    properties.put(ENTITY_NAME_KEY, artifactInfo.getName());
    ArtifactClasses classes = artifactInfo.getClasses();
    for (PluginClass pluginClass : classes.getPlugins()) {
        addPlugin(pluginClass, artifactInfo.getVersion(), properties);
    }
    if (!existing) {
        properties.put(CREATION_TIME_KEY, String.valueOf(System.currentTimeMillis()));
    }
    return properties.build();
}
Also used : ArtifactClasses(co.cask.cdap.api.artifact.ArtifactClasses) PluginClass(co.cask.cdap.api.plugin.PluginClass) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 3 with PluginClass

use of co.cask.cdap.api.plugin.PluginClass in project cdap by caskdata.

the class ArtifactInspector method inspectPlugins.

/**
 * Inspects the plugin file and extracts plugin classes information.
 */
private ArtifactClasses.Builder inspectPlugins(ArtifactClasses.Builder builder, File artifactFile, ArtifactId artifactId, PluginInstantiator pluginInstantiator) throws IOException, InvalidArtifactException {
    // See if there are export packages. Plugins should be in those packages
    Set<String> exportPackages = getExportPackages(artifactFile);
    if (exportPackages.isEmpty()) {
        return builder;
    }
    try {
        ClassLoader pluginClassLoader = pluginInstantiator.getArtifactClassLoader(artifactId);
        for (Class<?> cls : getPluginClasses(exportPackages, pluginClassLoader)) {
            Plugin pluginAnnotation = cls.getAnnotation(Plugin.class);
            if (pluginAnnotation == null) {
                continue;
            }
            Map<String, PluginPropertyField> pluginProperties = Maps.newHashMap();
            try {
                String configField = getProperties(TypeToken.of(cls), pluginProperties);
                Set<String> pluginEndpoints = getPluginEndpoints(cls);
                PluginClass pluginClass = new PluginClass(pluginAnnotation.type(), getPluginName(cls), getPluginDescription(cls), cls.getName(), configField, pluginProperties, pluginEndpoints);
                builder.addPlugin(pluginClass);
            } catch (UnsupportedTypeException e) {
                LOG.warn("Plugin configuration type not supported. Plugin ignored. {}", cls, e);
            }
        }
    } catch (Throwable t) {
        throw new InvalidArtifactException(String.format("Class could not be found while inspecting artifact for plugins. " + "Please check dependencies are available, and that the correct parent artifact was specified. " + "Error class: %s, message: %s.", t.getClass(), t.getMessage()), t);
    }
    return builder;
}
Also used : CloseableClassLoader(co.cask.cdap.api.artifact.CloseableClassLoader) UnsupportedTypeException(co.cask.cdap.api.data.schema.UnsupportedTypeException) PluginClass(co.cask.cdap.api.plugin.PluginClass) PluginPropertyField(co.cask.cdap.api.plugin.PluginPropertyField) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) Plugin(co.cask.cdap.api.annotation.Plugin)

Example 4 with PluginClass

use of co.cask.cdap.api.plugin.PluginClass in project cdap by caskdata.

the class PluginInstantiator method newInstance.

/**
 * Creates a new instance of the given plugin class with all property macros substituted if a MacroEvaluator is given.
 * At runtime, plugin property fields that are macro-enabled and contain macro syntax will remain in the macroFields
 * set in the plugin config.
 * @param plugin {@link Plugin}
 * @param macroEvaluator the MacroEvaluator that performs macro substitution
 * @param <T> Type of the plugin
 * @return a new plugin instance with macros substituted
 * @throws IOException if failed to expand the plugin jar to create the plugin ClassLoader
 * @throws ClassNotFoundException if failed to load the given plugin class
 */
public <T> T newInstance(Plugin plugin, @Nullable MacroEvaluator macroEvaluator) throws IOException, ClassNotFoundException, InvalidMacroException {
    ClassLoader classLoader = getPluginClassLoader(plugin);
    PluginClass pluginClass = plugin.getPluginClass();
    @SuppressWarnings("unchecked") TypeToken<T> pluginType = TypeToken.of((Class<T>) classLoader.loadClass(pluginClass.getClassName()));
    try {
        String configFieldName = pluginClass.getConfigFieldName();
        // Plugin doesn't have config. Simply return a new instance.
        if (configFieldName == null) {
            return instantiatorFactory.get(pluginType).create();
        }
        // Create the config instance
        Field field = Fields.findField(pluginType.getType(), configFieldName);
        TypeToken<?> configFieldType = pluginType.resolveType(field.getGenericType());
        Object config = instantiatorFactory.get(configFieldType).create();
        // perform macro substitution if an evaluator is provided, collect fields with macros only at configure time
        PluginProperties pluginProperties = substituteMacros(plugin, macroEvaluator);
        Set<String> macroFields = (macroEvaluator == null) ? getFieldsWithMacro(plugin) : Collections.emptySet();
        Reflections.visit(config, configFieldType.getType(), new ConfigFieldSetter(pluginClass, plugin.getArtifactId(), pluginProperties, macroFields));
        // Create the plugin instance
        return newInstance(pluginType, field, configFieldType, config);
    } catch (NoSuchFieldException e) {
        throw new InvalidPluginConfigException("Config field not found in plugin class: " + pluginClass, e);
    } catch (IllegalAccessException e) {
        throw new InvalidPluginConfigException("Failed to set plugin config field: " + pluginClass, e);
    }
}
Also used : PluginPropertyField(co.cask.cdap.api.plugin.PluginPropertyField) Field(java.lang.reflect.Field) CombineClassLoader(co.cask.cdap.common.lang.CombineClassLoader) PluginClass(co.cask.cdap.api.plugin.PluginClass) PluginProperties(co.cask.cdap.api.plugin.PluginProperties)

Example 5 with PluginClass

use of co.cask.cdap.api.plugin.PluginClass in project cdap by caskdata.

the class PluginFinderTestBase method testFindPlugin.

@Test
public void testFindPlugin() throws Exception {
    // Deploy some artifacts
    File appArtifact = createAppJar(PluginTestApp.class);
    File pluginArtifact = createPluginJar(Plugin1.class);
    ArtifactId appArtifactId = NamespaceId.DEFAULT.artifact("app", "1.0");
    artifactRepo.addArtifact(Id.Artifact.fromEntityId(appArtifactId), appArtifact);
    ArtifactId pluginArtifactId = NamespaceId.DEFAULT.artifact("plugin", "1.0");
    artifactRepo.addArtifact(Id.Artifact.fromEntityId(pluginArtifactId), pluginArtifact, Collections.singleton(new ArtifactRange(appArtifactId.getNamespace(), appArtifactId.getArtifact(), new ArtifactVersion(appArtifactId.getVersion()), true, new ArtifactVersion(appArtifactId.getVersion()), true)), null);
    // Find the plugin
    PluginFinder finder = getPluginFinder();
    Map.Entry<ArtifactDescriptor, PluginClass> entry = finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy", "Plugin1", new PluginSelector());
    Assert.assertNotNull(entry);
    Assert.assertEquals(pluginArtifactId.toApiArtifactId(), entry.getKey().getArtifactId());
    Assert.assertEquals("Plugin1", entry.getValue().getName());
    Assert.assertEquals("dummy", entry.getValue().getType());
    // Looking for a non-existing should throw
    try {
        finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy2", "pluginx", new PluginSelector());
        Assert.fail("A PluginNotExistsException is expected");
    } catch (PluginNotExistsException e) {
    // expected
    }
    // Deploy the same plugin artifact to the system namespace, without any parent
    ArtifactId systemPluginArtifactId = NamespaceId.SYSTEM.artifact("pluginsystem", "1.0");
    artifactRepo.addArtifact(Id.Artifact.fromEntityId(systemPluginArtifactId), pluginArtifact);
    entry = finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy", "Plugin1", new PluginSelector());
    // The selector always select the last one, hence the USER once will be selected
    Assert.assertNotNull(entry);
    Assert.assertEquals(pluginArtifactId.toApiArtifactId(), entry.getKey().getArtifactId());
    Assert.assertEquals("Plugin1", entry.getValue().getName());
    Assert.assertEquals("dummy", entry.getValue().getType());
    // Use a different selector that returns the first entry, hence expect the SYSTEM one being returned
    entry = finder.findPlugin(NamespaceId.DEFAULT, appArtifactId, "dummy", "Plugin1", new PluginSelector() {

        @Override
        public Map.Entry<co.cask.cdap.api.artifact.ArtifactId, PluginClass> select(SortedMap<co.cask.cdap.api.artifact.ArtifactId, PluginClass> plugins) {
            return plugins.entrySet().iterator().next();
        }
    });
    Assert.assertNotNull(entry);
    Assert.assertEquals(systemPluginArtifactId.toApiArtifactId(), entry.getKey().getArtifactId());
    Assert.assertEquals("Plugin1", entry.getValue().getName());
    Assert.assertEquals("dummy", entry.getValue().getType());
}
Also used : PluginSelector(co.cask.cdap.api.plugin.PluginSelector) ArtifactId(co.cask.cdap.proto.id.ArtifactId) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) PluginNotExistsException(co.cask.cdap.internal.app.runtime.plugin.PluginNotExistsException) ArtifactVersion(co.cask.cdap.api.artifact.ArtifactVersion) SortedMap(java.util.SortedMap) PluginClass(co.cask.cdap.api.plugin.PluginClass) File(java.io.File) Map(java.util.Map) SortedMap(java.util.SortedMap) Test(org.junit.Test)

Aggregations

PluginClass (co.cask.cdap.api.plugin.PluginClass)76 PluginPropertyField (co.cask.cdap.api.plugin.PluginPropertyField)46 HashMap (java.util.HashMap)37 Test (org.junit.Test)24 ArtifactId (co.cask.cdap.proto.id.ArtifactId)22 NamespaceId (co.cask.cdap.proto.id.NamespaceId)21 ArtifactRange (co.cask.cdap.api.artifact.ArtifactRange)19 ArtifactVersion (co.cask.cdap.api.artifact.ArtifactVersion)17 Id (co.cask.cdap.common.id.Id)17 Set (java.util.Set)14 ImmutableSet (com.google.common.collect.ImmutableSet)13 PluginNotExistsException (co.cask.cdap.internal.app.runtime.plugin.PluginNotExistsException)11 Map (java.util.Map)11 ArtifactNotFoundException (co.cask.cdap.common.ArtifactNotFoundException)10 SortedMap (java.util.SortedMap)10 ArtifactId (co.cask.cdap.api.artifact.ArtifactId)9 File (java.io.File)9 ApplicationClass (co.cask.cdap.api.artifact.ApplicationClass)8 HashSet (java.util.HashSet)8 ImmutableMap (com.google.common.collect.ImmutableMap)7