[java-shib-profile] 03/03: IDP-2121 Future Proofing the Module Plugin infrastructure for Future SP use
Rod Widdowson
rdw at steadingsoftware.com
Fri Jun 9 09:35:30 UTC 2023
This is an automated email from the git hooks/post-receive script.
rdw pushed a commit to branch main
in repository java-shib-profile.
View the commit online:
http://git.shibboleth.net/view/?p=java-shib-profile.git;a=commit;h=f1fe7542c6abc9a31b1f759636c414c51ebc3180
commit f1fe7542c6abc9a31b1f759636c414c51ebc3180
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Thu Jun 8 19:46:39 2023 +0100
IDP-2121 Future Proofing the Module Plugin infrastructure for Future SP use
https://shibboleth.atlassian.net/browse/IDP-2121
Push the Property driven Plugin down to shib-profile
---
.../shibboleth/profile/plugin/PluginException.java | 67 ++++++
.../profile/plugin/PropertyDrivenPlugin.java | 233 +++++++++++++++++++++
2 files changed, 300 insertions(+)
diff --git a/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PluginException.java b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PluginException.java
new file mode 100644
index 0000000..b82d945
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PluginException.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.profile.plugin;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Plugin exception class.
+ *
+ * @since 9.0.0
+ */
+ at ThreadSafe
+public class PluginException extends Exception {
+
+ /** Serial number. */
+ private static final long serialVersionUID = -2356509887689187370L;
+
+ /** Constructor. */
+ public PluginException() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message exception message
+ */
+ public PluginException(@Nullable final String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param wrappedException exception to be wrapped by this one
+ */
+ public PluginException(@Nullable final Exception wrappedException) {
+ super(wrappedException);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message exception message
+ * @param wrappedException exception to be wrapped by this one
+ */
+ public PluginException(@Nullable final String message, @Nullable final Exception wrappedException) {
+ super(message, wrappedException);
+ }
+
+}
\ 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
new file mode 100644
index 0000000..90f8173
--- /dev/null
+++ b/shib-profile-api/src/main/java/net/shibboleth/profile/plugin/PropertyDrivenPlugin.java
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.profile.plugin;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+
+import net.shibboleth.profile.installablecomponent.InstallableComponentVersion;
+import net.shibboleth.shared.annotation.constraint.NonNegative;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+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;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.profile.module.Module;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * Implementation of {@link IdPPlugin} relying on Java {@link Properties}.
+ *
+ * @since 4.1.0
+ */
+public abstract class PropertyDrivenPlugin<T extends Module> extends AbstractPlugin<T> implements Plugin<T> {
+
+ /** Default name of plugin properties resource. */
+ @Nonnull @NotEmpty public static final String DEFAULT_RESOURCE = "plugin.properties";
+
+ /** Property for plugin ID. */
+ @Nonnull @NotEmpty public static final String PLUGIN_ID_PROPERTY = "plugin.id";
+
+ /** Property for plugin version. */
+ @Nonnull @NotEmpty public static final String PLUGIN_VERSION_PROPERTY = "plugin.version";
+
+ /** Property for plugin license. */
+ @Nonnull @NotEmpty public static final String PLUGIN_LICENSE_PROPERTY = "plugin.license";
+
+ /** Prefix of property for plugin update URL. */
+ @Nonnull @NotEmpty public static final String PLUGIN_URL_PROPERTY = "plugin.url.";
+
+ /** Property for plugin's required modules. */
+ @Nonnull @NotEmpty public static final String PLUGIN_REQ_MODULES_PROPERTY = "plugin.modules.required";
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(PropertyDrivenPlugin.class);
+
+ /** Properties describing plugin. */
+ @Nonnull private final Properties pluginProperties;
+
+ /** Non-defaulted plugin ID. */
+ @Nullable private String pluginId;
+
+ /** Handles parsing of plugin version. */
+ @Nullable private InstallableComponentVersion pluginVersion;
+
+ /** Plugin update URLs. */
+ @Nonnull @NonnullElements private List<URL> updateURLs = CollectionSupport.emptyList();
+
+ /** Required modules. */
+ @Nonnull @NonnullElements private Set<String> requiredModules = CollectionSupport.emptySet();
+
+ /**
+ * 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(claz.getResourceAsStream(DEFAULT_RESOURCE));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param inputStream property stream
+ *
+ * @throws IOException if unable to read file
+ * @throws PluginException if the plugin is not in a valid state
+ */
+ public PropertyDrivenPlugin(@Nonnull final InputStream inputStream)
+ throws IOException, PluginException {
+ pluginProperties = new Properties();
+ pluginProperties.load(inputStream);
+ load();
+ }
+
+ /**
+ * 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));
+ if (version == null) {
+ throw new PluginException("No plugin version property or package attribute available for " + pluginId);
+ }
+ } else {
+ log.debug("Ignoring plugin '{}' version property in favor of package manifest", pluginId);
+ }
+
+ try {
+ pluginVersion = new InstallableComponentVersion(version);
+ } catch (final NumberFormatException e) {
+ throw new PluginException(e);
+ }
+
+ 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);
+
+ requiredModules = CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(
+ StringSupport.stringToList(pluginProperties.getProperty(PLUGIN_REQ_MODULES_PROPERTY, ""), ",")));
+
+ log.debug("Plugin {} loaded", getPluginId());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull @NotEmpty public String getPluginId() {
+ if (pluginId != null) {
+ return pluginId;
+ }
+ return super.getPluginId();
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull @NonnullElements @Unmodifiable @NotLive public List<URL> getUpdateURLs() {
+ return updateURLs;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull @NonnullElements @Unmodifiable @NotLive public Set<String> getRequiredModules() {
+ return requiredModules;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public String getLicenseFileLocation() {
+ return pluginProperties.getProperty(PLUGIN_LICENSE_PROPERTY);
+ }
+
+ /** {@inheritDoc} */
+ @NonNegative public int getMajorVersion() {
+ assert pluginVersion != null;
+ return pluginVersion.getMajor();
+ }
+
+ /** {@inheritDoc} */
+ @NonNegative public int getMinorVersion() {
+ assert pluginVersion != null;
+ return pluginVersion.getMinor();
+ }
+
+ /** {@inheritDoc} */
+ @NonNegative public int getPatchVersion() {
+ 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 @NonnullElements @Unmodifiable @NotLive protected List<URL> getDefaultUpdateURLs() throws PluginException {
+ return CollectionSupport.emptyList();
+ }
+
+}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list