use of io.cdap.cdap.api.annotation.Plugin in project cdap by caskdata.
the class DefaultArtifactInspector method isPlugin.
/**
* Detects if a class is annotated with {@link Plugin} without loading the class.
*
* @param className name of the class
* @param classLoader ClassLoader for loading the class file of the given class
* @return true if the given class is annotated with {@link Plugin}
*/
private boolean isPlugin(String className, ClassLoader classLoader) {
try (InputStream is = classLoader.getResourceAsStream(className.replace('.', '/') + ".class")) {
if (is == null) {
return false;
}
// Use ASM to inspect the class bytecode to see if it is annotated with @Plugin
final boolean[] isPlugin = new boolean[1];
ClassReader cr = new ClassReader(is);
cr.accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (Plugin.class.getName().equals(Type.getType(desc).getClassName()) && visible) {
isPlugin[0] = true;
}
return super.visitAnnotation(desc, visible);
}
}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return isPlugin[0];
} catch (IOException e) {
// If failed to open the class file, then it cannot be a plugin
LOG.warn("Failed to open class file for {}", className, e);
return false;
}
}
use of io.cdap.cdap.api.annotation.Plugin in project cdap by caskdata.
the class DefaultArtifactInspector method inspectPlugins.
/**
* Inspects the plugin file and extracts plugin classes information.
*/
private void inspectPlugins(ArtifactClasses.Builder builder, File artifactFile, io.cdap.cdap.proto.id.ArtifactId artifactId, PluginInstantiator pluginInstantiator, Set<PluginClass> additionalPlugins, List<MetadataMutation> mutations) throws IOException, InvalidArtifactException {
ArtifactId artifact = artifactId.toApiArtifactId();
PluginClassLoader pluginClassLoader = pluginInstantiator.getArtifactClassLoader(artifact);
inspectAdditionalPlugins(artifact, additionalPlugins, pluginClassLoader);
// See if there are export packages. Plugins should be in those packages
Set<String> exportPackages = getExportPackages(artifactFile);
if (exportPackages.isEmpty()) {
return;
}
try {
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);
String pluginName = getPluginName(cls);
PluginId pluginId = new PluginId(artifactId.getNamespace(), artifactId.getArtifact(), artifactId.getVersion(), pluginName, pluginAnnotation.type());
MetadataMutation mutation = getMetadataMutation(pluginId, cls);
if (mutation != null) {
mutations.add(mutation);
}
PluginClass pluginClass = PluginClass.builder().setName(pluginName).setType(pluginAnnotation.type()).setCategory(getPluginCategory(cls)).setClassName(cls.getName()).setConfigFieldName(configField).setProperties(pluginProperties).setRequirements(getArtifactRequirements(cls)).setDescription(getPluginDescription(cls)).build();
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);
}
}
Aggregations