/** * The plugin label is used in logging and it's a string in format {@code pluginId@pluginVersion}. */ protected String getPluginLabel(PluginDescriptor pluginDescriptor) { return pluginDescriptor.getPluginId() + "@" + pluginDescriptor.getVersion(); }
private String getDependencyVersionSupport(PluginDescriptor dependent, String dependencyId) { List<PluginDependency> dependencies = dependent.getDependencies(); for (PluginDependency dependency : dependencies) { if (dependencyId.equals(dependency.getPluginId())) { return dependency.getPluginVersionSupport(); } } throw new IllegalStateException("Cannot find a dependency with id '" + dependencyId + "' for plugin '" + dependent.getPluginId() + "'"); }
String pluginClassName = pluginWrapper.getDescriptor().getPluginClass(); log.debug("Create instance for plugin '{}'", pluginClassName);
/** * show the started plugins */ public void showStartedPlugins() { List<PluginWrapper> startedPlugins = pluginManager.getStartedPlugins(); for (PluginWrapper plugin : startedPlugins) { PluginDescriptor descriptor = plugin.getDescriptor(); String pluginId = plugin.getDescriptor().getPluginId(); String msg = String.format( "Extensions added by plugin id:'%s' version:'%s' %s:", pluginId, descriptor.getVersion(), descriptor.getPluginDescription()); if (debug) LOGGER.log(Level.INFO, msg); Set<String> extensionClassNames = pluginManager .getExtensionClassNames(pluginId); for (String extension : extensionClassNames) { msg = " " + extension; if (debug) LOGGER.log(Level.INFO, msg); } } }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + descriptor.getPluginId().hashCode(); return result; }
validatePluginDescriptor(pluginDescriptor); log.debug("Found descriptor {}", pluginDescriptor); String pluginClassName = pluginDescriptor.getPluginClass(); log.debug("Class '{}' for plugin '{}'", pluginClassName, pluginPath); if (isPluginDisabled(pluginDescriptor.getPluginId())) { log.info("Plugin '{}' is disabled", pluginPath); pluginWrapper.setPluginState(PluginState.DISABLED); pluginId = pluginDescriptor.getPluginId();
private Class<?> loadClassFromDependencies(String className) { log.trace("Search in dependencies for class '{}'", className); List<PluginDependency> dependencies = pluginDescriptor.getDependencies(); for (PluginDependency dependency : dependencies) { ClassLoader classLoader = pluginManager.getPluginClassLoader(dependency.getPluginId()); // If the dependency is marked as optional, its class loader might not be available. if (classLoader == null && dependency.isOptional()) { continue; } try { return classLoader.loadClass(className); } catch (ClassNotFoundException e) { // try next dependency } } return null; }
/** * Check if this plugin is valid (satisfies "requires" param) for a given system version. * * @param pluginWrapper the plugin to check * @return true if plugin satisfies the "requires" or if requires was left blank */ protected boolean isPluginValid(PluginWrapper pluginWrapper) { String requires = pluginWrapper.getDescriptor().getRequires().trim(); if (!isExactVersionAllowed() && requires.matches("^\\d+\\.\\d+\\.\\d+$")) { // If exact versions are not allowed in requires, rewrite to >= expression requires = ">=" + requires; } if (systemVersion.equals("0.0.0") || versionManager.checkVersionConstraint(systemVersion, requires)) { return true; } PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor(); log.warn("Plugin '{}' requires a minimum system version of {}, and you have {}", getPluginLabel(pluginDescriptor), pluginWrapper.getDescriptor().getRequires(), getSystemVersion()); return false; }
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } PluginWrapper other = (PluginWrapper) obj; if (!descriptor.getPluginId().equals(other.descriptor.getPluginId())) { return false; } return true; }
validatePluginDescriptor(pluginDescriptor); log.debug("Found descriptor {}", pluginDescriptor); String pluginClassName = pluginDescriptor.getPluginClass(); log.debug("Class '{}' for plugin '{}'", pluginClassName, pluginPath); if (isPluginDisabled(pluginDescriptor.getPluginId())) { log.info("Plugin '{}' is disabled", pluginPath); pluginWrapper.setPluginState(PluginState.DISABLED); pluginId = pluginDescriptor.getPluginId();
@Override public void pluginStateChanged(PluginStateEvent event) { // TODO optimize (do only for some transitions) // clear cache entries = null; // By default we're assuming, that no checks for extension dependencies are necessary. // // A plugin, that has an optional dependency to other plugins, might lead to unloadable // Java classes (NoClassDefFoundError) at application runtime due to possibly missing // dependencies. Therefore we're enabling the check for optional extensions, if the // started plugin contains at least one optional plugin dependency. if (checkForExtensionDependencies == null && PluginState.STARTED.equals(event.getPluginState())) { for (PluginDependency dependency : event.getPlugin().getDescriptor().getDependencies()) { if (dependency.isOptional()) { log.debug("Enable check for extension dependencies via ASM."); checkForExtensionDependencies = true; break; } } } }
/** * Check if this plugin is valid (satisfies "requires" param) for a given system version. * * @param pluginWrapper the plugin to check * @return true if plugin satisfies the "requires" or if requires was left blank */ protected boolean isPluginValid(PluginWrapper pluginWrapper) { String requires = pluginWrapper.getDescriptor().getRequires().trim(); if (!isExactVersionAllowed() && requires.matches("^\\d+\\.\\d+\\.\\d+$")) { // If exact versions are not allowed in requires, rewrite to >= expression requires = ">=" + requires; } if (systemVersion.equals("0.0.0") || versionManager.checkVersionConstraint(systemVersion, requires)) { return true; } PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor(); log.warn("Plugin '{}' requires a minimum system version of {}, and you have {}", getPluginLabel(pluginDescriptor), pluginWrapper.getDescriptor().getRequires(), getSystemVersion()); return false; }
/** * Override this to change the validation criteria. * * @param descriptor the plugin descriptor to validate * @throws PluginException if validation fails */ protected void validatePluginDescriptor(PluginDescriptor descriptor) throws PluginException { if (StringUtils.isNullOrEmpty(descriptor.getPluginId())) { throw new PluginException("Field 'id' cannot be empty"); } if (descriptor.getVersion() == null) { throw new PluginException("Field 'version' cannot be empty"); } }
/** * Shortcut */ public String getPluginId() { return getDescriptor().getPluginId(); }
private void addPlugin(PluginDescriptor descriptor) { String pluginId = descriptor.getPluginId(); List<PluginDependency> dependencies = descriptor.getDependencies(); if (dependencies.isEmpty()) { dependenciesGraph.addVertex(pluginId); dependentsGraph.addVertex(pluginId); } else { boolean edgeAdded = false; for (PluginDependency dependency : dependencies) { // Don't register optional plugins in the dependency graph to avoid automatic disabling of the plugin, // if an optional dependency is missing. if (!dependency.isOptional()) { edgeAdded = true; dependenciesGraph.addEdge(pluginId, dependency.getPluginId()); dependentsGraph.addEdge(dependency.getPluginId(), pluginId); } } // Register the plugin without dependencies, if all of its dependencies are optional. if (!edgeAdded) { dependenciesGraph.addVertex(pluginId); dependentsGraph.addVertex(pluginId); } } }
for (PluginDependency dependency : pluginDescriptor.getDependencies()) { startPlugin(dependency.getPluginId());
String pluginClassName = pluginWrapper.getDescriptor().getPluginClass(); log.debug("Create instance for plugin '{}'", pluginClassName);
for (PluginDescriptor plugin : plugins) { addPlugin(plugin); pluginByIds.put(plugin.getPluginId(), plugin); String pluginId = plugin.getPluginId(); String existingVersion = plugin.getVersion();
@Override public String loadPlugin(Path pluginPath) { if ((pluginPath == null) || Files.notExists(pluginPath)) { throw new IllegalArgumentException(String.format("Specified plugin %s does not exist!", pluginPath)); } log.debug("Loading plugin from '{}'", pluginPath); try { PluginWrapper pluginWrapper = loadPluginFromPath(pluginPath); // try to resolve the loaded plugin together with other possible plugins that depend on this plugin resolvePlugins(); return pluginWrapper.getDescriptor().getPluginId(); } catch (PluginException e) { log.error(e.getMessage(), e); } return null; }
private String getDependencyVersionSupport(PluginDescriptor dependent, String dependencyId) { List<PluginDependency> dependencies = dependent.getDependencies(); for (PluginDependency dependency : dependencies) { if (dependencyId.equals(dependency.getPluginId())) { return dependency.getPluginVersionSupport(); } } throw new IllegalStateException("Cannot find a dependency with id '" + dependencyId + "' for plugin '" + dependent.getPluginId() + "'"); }