From 2a446f6492130869c25492f31622b29d4d18cf63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf=20H=C3=B8gemark?= Date: Wed, 22 Nov 2023 18:38:18 +0100 Subject: [PATCH 1/3] Revert "Remove Java Plugin Framework core plugin file" This reverts commit 0db10a1a6caee8e8d71109a15c7ae64537cee965. --- osmosis-core/build.gradle | 31 +++++++++++++++++++ .../osmosis/core/plugin/plugin.xml.template | 9 ++++++ 2 files changed, 40 insertions(+) create mode 100644 osmosis-core/src/main/resources/org/openstreetmap/osmosis/core/plugin/plugin.xml.template diff --git a/osmosis-core/build.gradle b/osmosis-core/build.gradle index 15d3e1eeb..d01adea06 100644 --- a/osmosis-core/build.gradle +++ b/osmosis-core/build.gradle @@ -28,3 +28,34 @@ task generateJavaSources { // Define task dependency to ensure constants file is always up to date. compileJava.dependsOn generateJavaSources sourcesJar.dependsOn generateJavaSources + + +/* + * Define a custom task to automatically generate the plugin.xml file + * and update the copy resources task to depend on it. + */ +task generateResources { + description = 'Generates the plugin.xml file with the current version number.' + + // Build file objects for our template file, and output java file. + def commonPathPrefix = "$projectDir/src/main/resources/org/openstreetmap/osmosis/core/plugin/plugin.xml" + def outputFile = new File(commonPathPrefix) + def inputFile = new File(commonPathPrefix + ".template") + + /* + * Declare inputs and outputs of the task to allow gradle to determine if + * it is up to date. + */ + inputs.file inputFile + outputs.file outputFile + + doLast { + // Insert the version string into the constants file. + def fileContent = inputFile.getText() + fileContent = fileContent.replace("no-version-specified", version) + outputFile.write(fileContent) + } +} +// Define task dependency to ensure constants file is always up to date. +processResources.dependsOn generateResources +sourcesJar.dependsOn generateResources diff --git a/osmosis-core/src/main/resources/org/openstreetmap/osmosis/core/plugin/plugin.xml.template b/osmosis-core/src/main/resources/org/openstreetmap/osmosis/core/plugin/plugin.xml.template new file mode 100644 index 000000000..4f0e4fdcc --- /dev/null +++ b/osmosis-core/src/main/resources/org/openstreetmap/osmosis/core/plugin/plugin.xml.template @@ -0,0 +1,9 @@ + + + + + + + + From 9130aae99cf4cf70f4a265baf609407231febea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf=20H=C3=B8gemark?= Date: Wed, 22 Nov 2023 18:40:32 +0100 Subject: [PATCH 2/3] Revert "Remove Java Plugin Framework" This reverts the main part of commit 95a380b3724159965cc0535116057d30e42d65ff, i.e. all of the Java changes are reverted. Got conflict when reverting the whole commit, so I had to add the dependency towards JPF to the osmosis-core/build.gradle file manually. --- gradle.properties | 1 + osmosis-core/build.gradle | 4 + .../osmosis/core/TaskRegistrar.java | 183 +++++++++++++++++- .../osmosis/core/plugin/CorePlugin.java | 30 +++ 4 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java diff --git a/gradle.properties b/gradle.properties index 6a3482892..5b6432553 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,6 +14,7 @@ dependencyVersionCommonsIo=2.15.0 # Should we be using Dbcp2? dependencyVersionCommonsDbcp=1.4 dependencyVersionGuava=32.1.3-jre +dependencyVersionJpf=1.5 # JUnit 5 is available, some re-write required dependencyVersionJunit=4.13.2 dependencyVersionMySql=8.0.33 diff --git a/osmosis-core/build.gradle b/osmosis-core/build.gradle index d01adea06..85727217d 100644 --- a/osmosis-core/build.gradle +++ b/osmosis-core/build.gradle @@ -1,3 +1,7 @@ +dependencies { + implementation group: 'net.sf.jpf', name: 'jpf', version: dependencyVersionJpf +} + /* * Define a custom task to automatically generate the OsmosisConstants file * and update the java compilation task to depend on it. diff --git a/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java index 44d2785d1..943c2e9bd 100644 --- a/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java +++ b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java @@ -2,17 +2,31 @@ package org.openstreetmap.osmosis.core; import java.io.BufferedReader; +import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Logger; +import org.java.plugin.JpfException; +import org.java.plugin.ObjectFactory; +import org.java.plugin.PluginLifecycleException; +import org.java.plugin.PluginManager; +import org.java.plugin.PluginManager.PluginLocation; +import org.java.plugin.registry.Extension; +import org.java.plugin.registry.ExtensionPoint; +import org.java.plugin.registry.ManifestProcessingException; +import org.java.plugin.registry.PluginDescriptor; +import org.java.plugin.standard.StandardPluginLocation; import org.openstreetmap.osmosis.core.pipeline.common.TaskManagerFactory; import org.openstreetmap.osmosis.core.pipeline.common.TaskManagerFactoryRegister; import org.openstreetmap.osmosis.core.plugin.PluginLoader; @@ -69,6 +83,9 @@ public void initialize(List plugins) { for (String plugin : plugins) { loadPlugin(plugin); } + + // Register the plugins loaded via JPF. + loadJPFPlugins(); } /** @@ -129,6 +146,162 @@ private void loadBuiltInPlugins() { } + /** + * Loads the tasks implemented as plugins. + * + */ + private void loadJPFPlugins() { + PluginManager pluginManager; + + // Create a new JPF plugin manager. + pluginManager = ObjectFactory.newInstance().createManager(); + + // Search known locations for plugin files. + LOG.fine("Searching for JPF plugins."); + List locations = gatherJpfPlugins(); + + // Register the core plugin. + LOG.fine("Registering the core plugin."); + registerCorePlugin(pluginManager); + + // Register all located plugins. + LOG.fine("Registering the extension plugins."); + if (locations.size() == 0) { + // There are no plugins available so stop processing here. + return; + } + registerJpfPlugins(pluginManager, locations); + + // Initialise all of the plugins that have been registered. + LOG.fine("Activating the plugins."); + // load plugins for the task-extension-point + PluginDescriptor core = pluginManager.getRegistry() + .getPluginDescriptor("org.openstreetmap.osmosis.core.plugin.Core"); + + ExtensionPoint point = pluginManager.getRegistry().getExtensionPoint(core.getId(), "Task"); + for (Iterator it = point.getConnectedExtensions().iterator(); it.hasNext();) { + + Extension ext = it.next(); + PluginDescriptor descr = ext.getDeclaringPluginDescriptor(); + try { + pluginManager.enablePlugin(descr, true); + pluginManager.activatePlugin(descr.getId()); + ClassLoader classLoader = pluginManager.getPluginClassLoader(descr); + loadPluginClass(ext.getParameter("class").valueAsString(), classLoader); + } catch (PluginLifecycleException e) { + throw new OsmosisRuntimeException("Cannot load JPF-plugin '" + ext.getId() + + "' for extensionpoint '" + ext.getExtendedPointId() + "'", e); + } + } + } + + + /** + * Register the core plugin from which other plugins will extend. + * + * @param pluginManager + * The plugin manager to register the plugin with. + */ + private void registerCorePlugin(PluginManager pluginManager) { + try { + URL core; + PluginDescriptor coreDescriptor; + + // Get the plugin configuration file. + core = getClass().getResource("/org/openstreetmap/osmosis/core/plugin/plugin.xml"); + LOG.finest("Plugin URL: " + core); + + // Register the core plugin in the plugin registry. + pluginManager.getRegistry().register(new URL[] {core}); + + // Get the plugin descriptor from the registry. + coreDescriptor = pluginManager.getRegistry().getPluginDescriptor( + "org.openstreetmap.osmosis.core.plugin.Core"); + + // Enable the plugin. + pluginManager.enablePlugin(coreDescriptor, true); + pluginManager.activatePlugin("org.openstreetmap.osmosis.core.plugin.Core"); + + } catch (ManifestProcessingException e) { + throw new OsmosisRuntimeException("Unable to register core plugin.", e); + } catch (PluginLifecycleException e) { + throw new OsmosisRuntimeException("Unable to enable core plugin.", e); + } + } + + + /** + * Register the given JPF-plugins with the {@link PluginManager}. + * + * @param locations + * the plugins found + */ + private void registerJpfPlugins(PluginManager pluginManager, List locations) { + if (locations == null) { + throw new IllegalArgumentException("null plugin-list given"); + } + + try { + pluginManager.publishPlugins(locations.toArray(new PluginLocation[locations.size()])); + } catch (JpfException e) { + throw new OsmosisRuntimeException("Unable to publish plugins.", e); + } + } + + + /** + * @return a list of all JPF-plugins found. + */ + private List gatherJpfPlugins() { + File[] pluginsDirs = new File[] { + new File("plugins"), + new File(System.getProperty("user.home") + "/.openstreetmap" + File.separator + "osmosis" + + File.separator + "plugins"), + new File(System.getenv("APPDATA") + File.separator + "openstreetmap" + File.separator + "osmosis" + + File.separator + "plugins") + + }; + + FilenameFilter pluginFileNameFilter = new FilenameFilter() { + + /** + * @param dir + * the directory of the file + * @param name + * the unqualified name of the file + * @return true if this may be a plugin-file + */ + public boolean accept(final File dir, final String name) { + return name.toLowerCase().endsWith(".zip") || name.toLowerCase().endsWith(".jar"); + } + }; + List locations = new LinkedList(); + for (File pluginDir : pluginsDirs) { + LOG.finer("Loading plugins in " + pluginDir.getAbsolutePath()); + if (!pluginDir.exists()) { + continue; + } + File[] plugins = pluginDir.listFiles(pluginFileNameFilter); + try { + for (int i = 0; i < plugins.length; i++) { + LOG.finest("Found plugin " + plugins[i].getAbsolutePath()); + PluginLocation location = StandardPluginLocation.create(plugins[i]); + + if (location != null) { + locations.add(location); + } else { + LOG.warning("JPF Plugin " + plugins[i].getAbsolutePath() + + " is malformed and cannot be loaded."); + } + } + } catch (MalformedURLException e) { + throw new OsmosisRuntimeException("Cannot create plugin location " + pluginDir.getAbsolutePath(), e); + } + } + return locations; + } + + /** * Loads the tasks associated with a plugin (old plugin-api). * @@ -175,13 +348,7 @@ private void loadPluginClass(final String pluginClassName, final ClassLoader cla // Instantiate the plugin loader. try { - pluginLoader = pluginClass.getDeclaredConstructor().newInstance(); - } catch (InvocationTargetException e) { - throw new IllegalArgumentException("Unable to instantiate plugin class (" + pluginClassName + ").", e); - } catch (SecurityException e) { - throw new IllegalArgumentException("Unable to instantiate plugin class (" + pluginClassName + ").", e); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("Unable to instantiate plugin class (" + pluginClassName + ").", e); + pluginLoader = pluginClass.newInstance(); } catch (InstantiationException e) { throw new IllegalArgumentException("Unable to instantiate plugin class (" + pluginClassName + ").", e); } catch (IllegalAccessException e) { diff --git a/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java new file mode 100644 index 000000000..68f60a492 --- /dev/null +++ b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java @@ -0,0 +1,30 @@ +// This software is released into the Public Domain. See copying.txt for details. +package org.openstreetmap.osmosis.core.plugin; + +import org.java.plugin.Plugin; + + +/** + * The core plugin entry point. + * + * @author Marcus Wolschon + */ +public class CorePlugin extends Plugin { + + /** + * {@inheritDoc} + */ + @Override + protected void doStart() throws Exception { + // ignored + } + + + /** + * {@inheritDoc} + */ + @Override + protected void doStop() throws Exception { + // ignored + } +} From 26188585af1bd599ae8c8c7b6e67de14c3f4bdca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf=20H=C3=B8gemark?= Date: Sun, 26 Nov 2023 10:24:47 +0100 Subject: [PATCH 3/3] Remove whitespace at end of lines in JPF related files --- .../osmosis/core/TaskRegistrar.java | 55 +++++++++---------- .../osmosis/core/plugin/CorePlugin.java | 2 +- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java index 943c2e9bd..7b152b04f 100644 --- a/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java +++ b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/TaskRegistrar.java @@ -60,7 +60,7 @@ public TaskRegistrar() { /** * Returns the configured task manager factory register configured. - * + * * @return The task manager factory register. */ public TaskManagerFactoryRegister getFactoryRegister() { @@ -71,7 +71,7 @@ public TaskManagerFactoryRegister getFactoryRegister() { /** * Initialises factories for all tasks. Loads additionally specified plugins * as well as default tasks. - * + * * @param plugins * The class names of all plugins to be loaded. */ @@ -83,14 +83,14 @@ public void initialize(List plugins) { for (String plugin : plugins) { loadPlugin(plugin); } - + // Register the plugins loaded via JPF. loadJPFPlugins(); } /** * Loads a plugin manually. - * + * * @param pluginLoader The pluginLoader that you wish to load. */ public void loadPlugin(final PluginLoader pluginLoader) { @@ -105,39 +105,38 @@ public void loadPlugin(final PluginLoader pluginLoader) { private void loadBuiltInPlugins() { final String pluginResourceName = "osmosis-plugins.conf"; - + try { for (URL pluginConfigurationUrl : Collections.list(Thread.currentThread() .getContextClassLoader().getResources(pluginResourceName))) { BufferedReader pluginReader; - + LOG.finer("Loading plugin configuration file from url " + pluginConfigurationUrl + "."); - + try (InputStream pluginInputStream = pluginConfigurationUrl.openStream()) { if (pluginInputStream == null) { throw new OsmosisRuntimeException("Cannot open URL " + pluginConfigurationUrl + "."); } - + pluginReader = new BufferedReader(new InputStreamReader(pluginInputStream)); - + for (;;) { String plugin; - + plugin = pluginReader.readLine(); if (plugin == null) { break; } - + plugin = plugin.trim(); if (!plugin.isEmpty()) { LOG.finer("Loading plugin via loader " + plugin + "."); - + loadPlugin(plugin); } } } } - } catch (IOException e) { throw new OsmosisRuntimeException( "Unable to load the plugins based on " + pluginResourceName @@ -148,22 +147,22 @@ private void loadBuiltInPlugins() { /** * Loads the tasks implemented as plugins. - * + * */ private void loadJPFPlugins() { PluginManager pluginManager; - + // Create a new JPF plugin manager. pluginManager = ObjectFactory.newInstance().createManager(); - + // Search known locations for plugin files. LOG.fine("Searching for JPF plugins."); List locations = gatherJpfPlugins(); - + // Register the core plugin. LOG.fine("Registering the core plugin."); registerCorePlugin(pluginManager); - + // Register all located plugins. LOG.fine("Registering the extension plugins."); if (locations.size() == 0) { @@ -171,7 +170,7 @@ private void loadJPFPlugins() { return; } registerJpfPlugins(pluginManager, locations); - + // Initialise all of the plugins that have been registered. LOG.fine("Activating the plugins."); // load plugins for the task-extension-point @@ -198,7 +197,7 @@ private void loadJPFPlugins() { /** * Register the core plugin from which other plugins will extend. - * + * * @param pluginManager * The plugin manager to register the plugin with. */ @@ -206,22 +205,22 @@ private void registerCorePlugin(PluginManager pluginManager) { try { URL core; PluginDescriptor coreDescriptor; - + // Get the plugin configuration file. core = getClass().getResource("/org/openstreetmap/osmosis/core/plugin/plugin.xml"); LOG.finest("Plugin URL: " + core); - + // Register the core plugin in the plugin registry. pluginManager.getRegistry().register(new URL[] {core}); - + // Get the plugin descriptor from the registry. coreDescriptor = pluginManager.getRegistry().getPluginDescriptor( "org.openstreetmap.osmosis.core.plugin.Core"); - + // Enable the plugin. pluginManager.enablePlugin(coreDescriptor, true); pluginManager.activatePlugin("org.openstreetmap.osmosis.core.plugin.Core"); - + } catch (ManifestProcessingException e) { throw new OsmosisRuntimeException("Unable to register core plugin.", e); } catch (PluginLifecycleException e) { @@ -232,7 +231,7 @@ private void registerCorePlugin(PluginManager pluginManager) { /** * Register the given JPF-plugins with the {@link PluginManager}. - * + * * @param locations * the plugins found */ @@ -304,7 +303,7 @@ public boolean accept(final File dir, final String name) { /** * Loads the tasks associated with a plugin (old plugin-api). - * + * * @param plugin * The plugin loader class name. */ @@ -322,7 +321,7 @@ private void loadPlugin(final String plugin) { /** * Load the given plugin, old API or new JPF. - * + * * @param pluginClassName * the name of the class to instantiate * @param classLoader diff --git a/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java index 68f60a492..e9d06b0b0 100644 --- a/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java +++ b/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/plugin/CorePlugin.java @@ -6,7 +6,7 @@ /** * The core plugin entry point. - * + * * @author Marcus Wolschon */ public class CorePlugin extends Plugin {