[java-shib-profile] 01/02: IDP-2297 Explore extending the Plugin and Module Infrastructure to allow Jetty installation

Rod Widdowson rdw at steadingsoftware.com
Tue Jul 30 19:03:37 UTC 2024


This is an automated email from the git hooks/post-receive script.

rdw pushed a commit to branch dev/IDP-2297
in repository java-shib-profile.

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-profile.git;a=commit;h=cfddf6886a59b88952f000a5d85cb7dc39a192ac

commit cfddf6886a59b88952f000a5d85cb7dc39a192ac
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Thu Jul 25 10:32:21 2024 +0100

    IDP-2297 Explore extending the Plugin and Module Infrastructure to allow Jetty installation
    
    https://shibboleth.atlassian.net/browse/IDP-2297
    
    Teach Plugins about "Packages"
---
 .../shibboleth/profile/plugin/AbstractPlugin.java  |  24 ++-
 .../java/net/shibboleth/profile/plugin/Plugin.java |  34 ++++
 .../profile/plugin/PropertyDrivenPlugin.java       | 172 +++++++++++++++++----
 3 files changed, 199 insertions(+), 31 deletions(-)

diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/AbstractPlugin.java b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/AbstractPlugin.java
index ee6ba09..bb242df 100644
--- a/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/AbstractPlugin.java
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/AbstractPlugin.java
@@ -14,6 +14,8 @@
 
 package net.shibboleth.profile.plugin;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 import javax.annotation.Nonnegative;
@@ -39,6 +41,9 @@ public abstract class AbstractPlugin<T extends Module> implements Plugin<T> {
     /** Modules to disable on removal. */
     @Nonnull private Set<T> disableModules;
 
+	/** Packages to unpack. */
+	@Nonnull private List<Package> packages = CollectionSupport.emptyList();
+
     /** Constructor. */
     public AbstractPlugin() {
         enableModules = CollectionSupport.emptySet();
@@ -97,10 +102,23 @@ public abstract class AbstractPlugin<T extends Module> implements Plugin<T> {
 
     /** {@inheritDoc} */
     @Override
-    public boolean equals(final Object obj) {
-        return obj instanceof Plugin && getPluginId().equals(((Plugin<?>) obj).getPluginId());
+    @Nonnull
+    public Collection<Package> getPackages() {
+    	return packages;
+    }
+    
+    /** Set the packages to transfer
+     * @param input what to set
+     */
+    public void setPackages(@Nonnull Collection<Package> input) {
+    	packages = CollectionSupport.copyToList(input);
     }
 
+	/** {@inheritDoc} */
+	@Override
+	public boolean equals(final Object obj) {
+	    return obj instanceof Plugin && getPluginId().equals(((Plugin<?>) obj).getPluginId());
+	}
 
     /** {@inheritDoc} */
     @Override
@@ -113,5 +131,5 @@ public abstract class AbstractPlugin<T extends Module> implements Plugin<T> {
     public String toString() {
         return "Plugin " + getPluginId();
     }
-
+    
 }
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/Plugin.java b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/Plugin.java
index 543ef65..4bc697d 100644
--- a/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/Plugin.java
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/Plugin.java
@@ -16,6 +16,7 @@ package net.shibboleth.profile.plugin;
 
 import java.io.IOException;
 import java.net.URL;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -27,6 +28,7 @@ import net.shibboleth.profile.module.Module;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.annotation.constraint.NotLive;
 import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
 
 /**
  * The base interface for plugins into the IdP and SP.
@@ -104,4 +106,36 @@ public interface Plugin<T extends Module> {
      */
     @Nonnull @Unmodifiable @NotLive Set<T> getDisableOnRemoval();
 
+    /**
+     * Get the things to explicitly install.
+     * 
+     * @return what to install
+     */
+    default @Nonnull @Unmodifiable @NotLive Collection<Package> getPackages() {
+    	return CollectionSupport.emptySet();
+    }
+
+    /** An abstraction for "a thing that we want to unpack into idp home (outside webapps)". */
+    interface Package {
+
+    	/** Where in the zip file is the file.
+    	 * @return the location.
+    	 */
+    	@Nonnull @Unmodifiable @NotLive String getSourceName();
+
+    	/** Where the file/string has to be unpacked to (relative to idp.home).
+    	 * @return the location
+    	 */
+    	@Nonnull @Unmodifiable @NotLive String getDestinationName();
+    	
+    	/** Is this package for Windows Only?
+    	 * @return true if it is
+    	 */
+    	boolean isWindows();
+
+    	/** Is this package for non-windows Only?
+    	 * @return
+    	 */
+    	boolean isNonWindows();
+    }
 }
\ No newline at end of file
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PropertyDrivenPlugin.java b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PropertyDrivenPlugin.java
index 0991ad3..a783d81 100644
--- a/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PropertyDrivenPlugin.java
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PropertyDrivenPlugin.java
@@ -19,6 +19,7 @@ import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Properties;
 import java.util.Set;
@@ -41,9 +42,9 @@ import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * Implementation of {@link Plugin} relying on Java {@link Properties}.
- * 
+ *
  * @param <T> module type
- * 
+ *
  * @since 4.1.0
  */
 public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlugin<T> implements Plugin<T> {
@@ -66,6 +67,21 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
     /** Property for plugin's required modules. */
     @Nonnull @NotEmpty public static final String PLUGIN_REQ_MODULES_PROPERTY = "plugin.modules.required";
 
+    /** Prefix for the properties for plugin's packages. */
+    @Nonnull @NotEmpty public static final String PLUGIN_PACKAGE_PROPERTY = "plugin.package.";
+
+    /** Postfix for the source package properties. */
+    @Nonnull @NotEmpty public static final String PLUGIN_PACKAGE_SOURCE_PROPERTY = ".source";
+
+    /** Postfix for the destination package properties. */
+    @Nonnull @NotEmpty public static final String PLUGIN_PACKAGE_DESTNATION_PROPERTY = ".destination";
+
+    /** Postfix for the windows package properties. */
+    @Nonnull @NotEmpty public static final String PLUGIN_PACKAGE_WINDOWS_PROPERTY = ".windows";
+
+    /** Postfix for the non-windows package properties. */
+    @Nonnull @NotEmpty public static final String PLUGIN_PACKAGE_NONWINDOWS_PROPERTY = ".nonwindows";
+
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(PropertyDrivenPlugin.class);
 
@@ -74,13 +90,13 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
 
     /** Non-defaulted plugin ID. */
     @Nullable private String pluginId;
-    
+
     /** Handles parsing of plugin version. */
     @Nullable private InstallableComponentVersion pluginVersion;
-    
+
     /** Plugin update URLs. */
     @Nonnull private List<URL> updateURLs = CollectionSupport.emptyList();
-    
+
     /** Required modules. */
     @Nonnull private Set<String> requiredModules = CollectionSupport.emptySet();
 
@@ -88,19 +104,19 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
      * Constructor.
      *
      * @param claz type of object used to locate default module.properties resource
-     * 
+     *
      * @throws IOException if unable to read file
      * @throws PluginException if the plugin is not in a valid state
      */
     public PropertyDrivenPlugin(@Nonnull final Class<? extends Plugin<T>> claz) throws IOException, PluginException {
         this(Constraint.isNotNull(claz.getResourceAsStream(DEFAULT_RESOURCE), "never get: null resource stream"));
     }
-    
+
     /**
      * Constructor.
      *
      * @param inputStream property stream
-     * 
+     *
      * @throws IOException if unable to read file
      * @throws PluginException if the plugin is not in a valid state
      */
@@ -114,23 +130,23 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
      * Constructor.
      *
      * @param properties property set
-     * 
+     *
      * @throws PluginException if the plugin is not in a valid state
      */
     public PropertyDrivenPlugin(@Nonnull final Properties properties) throws PluginException {
         pluginProperties = Constraint.isNotNull(properties, "Properties cannot be null");
         load();
     }
-    
+
     /**
      * Load plugin information from properties.
-     * 
+     *
      * @throws PluginException on errors
      */
     protected void load() throws PluginException {
-        
+
         pluginId = StringSupport.trimOrNull(pluginProperties.getProperty(PLUGIN_ID_PROPERTY));
-        
+
         String version = getClass().getPackage().getImplementationVersion();
         if (version == null) {
             version = StringSupport.trimOrNull(pluginProperties.getProperty(PLUGIN_VERSION_PROPERTY));
@@ -139,7 +155,7 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
             }
             log.debug("Using plugin '{}' version property in favor of absent package manifest", pluginId);
         }
-        
+
         try {
             pluginVersion = new InstallableComponentVersion(version);
         } catch (final NumberFormatException e) {
@@ -147,33 +163,58 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
         }
 
         final List<URL> urls = new ArrayList<>();
-        
+
         for (Integer urlnum = 1; ; ++urlnum) {
-            
+
             final String urlstr = pluginProperties.getProperty(PLUGIN_URL_PROPERTY + urlnum.toString());
             if (urlstr == null) {
                 break;
             }
-            
+
             try {
                 urls.add(new URL(urlstr));
             } catch (final MalformedURLException e) {
                 log.error("Unable to convert property value '{}' to URL", urlstr, e);
             }
         }
-        
         urls.addAll(getDefaultUpdateURLs());
-        
+
         updateURLs = CollectionSupport.copyToList(urls);
-        
-		final String propVals = pluginProperties.getProperty(PLUGIN_REQ_MODULES_PROPERTY, "");
-		assert propVals != null;
+
+        final String propVals = pluginProperties.getProperty(PLUGIN_REQ_MODULES_PROPERTY, "");
+        assert propVals != null;
 
         requiredModules = CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(StringSupport.stringToList(propVals, ",")));
+        final HashSet<Plugin.Package> packages = new HashSet<Plugin.Package>();
+
+        for (Integer packageNum = 1; ; ++packageNum) {
+            final String packageNumStr = packageNum.toString();
+            final String srcStr = pluginProperties.getProperty(PLUGIN_PACKAGE_PROPERTY + packageNumStr + PLUGIN_PACKAGE_SOURCE_PROPERTY);
+            if (srcStr == null) {
+                break;
+            }
+            final String destStr = pluginProperties.getProperty(PLUGIN_PACKAGE_PROPERTY + packageNumStr + PLUGIN_PACKAGE_DESTNATION_PROPERTY);
+            if (destStr == null) {
+                log.error("Plugin {} no destination index {} (source = {}", pluginId, packageNum, srcStr);
+                break;
+            }
+            final boolean nonWin =  Boolean.valueOf(
+                 pluginProperties.getProperty(PLUGIN_PACKAGE_PROPERTY  + packageNumStr + PLUGIN_PACKAGE_NONWINDOWS_PROPERTY, "false"));
+            final boolean win =  Boolean.valueOf(
+                 pluginProperties.getProperty(PLUGIN_PACKAGE_PROPERTY  + packageNumStr + PLUGIN_PACKAGE_WINDOWS_PROPERTY, "false"));
+
+            packages.add(new PackageDescriptor(srcStr, destStr, nonWin, win));
+        }
+        setPackages(packages);
+
+        final String reqModules = pluginProperties.getProperty(PLUGIN_REQ_MODULES_PROPERTY, "");
+        assert reqModules != null;
+        requiredModules = CollectionSupport.copyToSet(
+	   StringSupport.normalizeStringCollection(StringSupport.stringToList(reqModules , ",")));
 
         log.debug("Plugin {} loaded", getPluginId());
     }
-    
+
     /** {@inheritDoc} */
     @Override
     @Nonnull @NotEmpty public String getPluginId() {
@@ -182,7 +223,7 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
         }
         return super.getPluginId();
     }
-    
+
     /** {@inheritDoc} */
     @Nonnull @Unmodifiable @NotLive public List<URL> getUpdateURLs() {
         return updateURLs;
@@ -217,15 +258,90 @@ public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlu
         assert pluginVersion != null;
         return pluginVersion.getPatch();
     }
-    
+
     /**
      * Provides default update locations to use.
-     * 
+     *
      * @return default update locations
      * @throws PluginException if a derived class throws it (see derived classes)
      */
     @Nonnull @Unmodifiable @NotLive protected List<URL> getDefaultUpdateURLs() throws PluginException {
         return CollectionSupport.emptyList();
     }
-    
-}
\ No newline at end of file
+
+    /** Implementation of {@link Plugin.Package} for our use. */
+    private static class PackageDescriptor implements Package {
+
+        /** What to return to {@link Plugin.Package#getSourceName()}. */
+        @Nonnull private final String source;
+
+        /** What to return to {@link Plugin.Package#getDestinationName()}. */
+        @Nonnull private final String destination;
+
+        /** What to return to {@link Plugin.Package#isNonWindows()}. */
+        private final boolean nonWindows;
+
+        /** What to return to {@link Plugin.Package#isWindows()}. */
+        private final boolean windows;
+
+        /**
+         * Constructor.
+         *
+         * @param src for {@link #getSourceName()}
+         * @param dest for {@link #getDestinationName()}
+         * @param nonWin for{@link #isNonWindows()}
+         * @param win for {@link #isWindows()}
+         */
+        private PackageDescriptor(@Nonnull final String src, @Nonnull final String dest, final boolean nonWin, final boolean win) {
+            source = src;
+            destination = dest;
+            nonWindows = nonWin;
+            windows = win;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        @Nonnull
+        public String getSourceName() {
+            return source;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        @Nonnull
+        public String getDestinationName() {
+            return destination;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public boolean isWindows() {
+            return windows;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public boolean isNonWindows() {
+            return nonWindows;
+        }
+
+        /** {@inheritDoc}.  Hashing and equality os slightly weird because we want to deduplicate on {{@link #destination} only */
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null) {
+                return false;
+            }
+            if (obj instanceof PackageDescriptor desc) {
+                return desc.destination.equals(destination);
+            }
+            return false;
+        }
+
+        /** {@inheritDoc}.  Hashing and equality os slightly weird because we want to deduplicate on {{@link #destination} only */
+        @Override
+        public int hashCode() {
+            return destination.hashCode();
+        }
+
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list