[java-identity-provider] branch main updated: IDP-1664 - Support Module service API

Scott Cantor cantor.2 at osu.edu
Tue Sep 22 15:55:10 UTC 2020


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

scantor pushed a commit to branch main
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=3c00e3644bc93b5ba80d7a82e31f55672f98137f

The following commit(s) were added to refs/heads/main by this push:
       new  3c00e3644 IDP-1664 - Support Module service API
3c00e3644 is described below

commit 3c00e3644bc93b5ba80d7a82e31f55672f98137f
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Sep 22 11:55:07 2020 -0400

    IDP-1664 - Support Module service API
    
    https://issues.shibboleth.net/jira/browse/IDP-1664
    
    Add i18n support to various fields and CLI.
---
 .../java/net/shibboleth/idp/module/IdPModule.java  |  8 ++-
 .../net/shibboleth/idp/module/ModuleContext.java   | 31 +++++++++++
 .../idp/module/PropertyDrivenIdPModule.java        | 64 ++++++++++++++++++++--
 .../net/shibboleth/idp/module/IdPModuleTest.java   | 15 ++++-
 .../net/shibboleth/idp/module/module.properties    |  3 +
 .../idp/module/impl/ModuleManagerCLI.java          |  5 +-
 idp-war/src/main/webapp/WEB-INF/jsp/status.jsp     |  2 +-
 7 files changed, 118 insertions(+), 10 deletions(-)

diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java
index 0a78b1501..b2b7c331f 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java
@@ -43,16 +43,20 @@ public interface IdPModule extends IdentifiedComponent {
     /**
      * Gets module name.
      * 
+     * @param moduleContext optional context for supplying i18n input
+     * 
      * @return a human-readable name for the module
      */
-    @Nonnull @NotEmpty String getName();
+    @Nonnull @NotEmpty String getName(@Nullable final ModuleContext moduleContext);
     
     /**
      * Gets module description.
      * 
+     * @param moduleContext optional context for supplying i18n input
+     * 
      * @return a human-readable description for the module
      */
-    @Nullable @NotEmpty String getDescription();
+    @Nullable @NotEmpty String getDescription(@Nullable final ModuleContext moduleContext);
 
     /**
      * Gets module URL.
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java
index 8997395ed..9883fd15d 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java
@@ -19,6 +19,9 @@ package net.shibboleth.idp.module;
 
 import java.io.PrintStream;
 import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale.LanguageRange;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -26,7 +29,10 @@ import javax.annotation.Nullable;
 import org.apache.http.client.HttpClient;
 import org.opensaml.security.httpclient.HttpClientSecurityParameters;
 
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 
 /**
@@ -45,6 +51,9 @@ public final class ModuleContext {
     /** HTTP security parameters. */
     @Nullable private HttpClientSecurityParameters httpClientSecurityParams;
     
+    /** Language expressions to use for i18n. */
+    @Nonnull @NonnullElements private List<LanguageRange> languageRanges;
+    
     /** Output stream for sending output to the module consumer. */
     @Nullable private PrintStream messageStream;
 
@@ -110,6 +119,28 @@ public final class ModuleContext {
     public void setHttpClientSecurityParameters(@Nullable final HttpClientSecurityParameters params) {
         httpClientSecurityParams = params;
     }
+    
+    /**
+     * Gets the language ranges to use for i18n.
+     * 
+     * @return language ranges
+     */
+    @Nonnull @NonnullElements @NotLive @Unmodifiable public List<LanguageRange> getLanguageRanges() {
+        return languageRanges;
+    }
+    
+    /**
+     * Sets the language ranges to use for i18n.
+     * 
+     * @param ranges language ranges
+     */
+    public void setLanguageRanges(@Nullable @NonnullElements final List<LanguageRange> ranges) {
+        if (ranges != null) {
+            languageRanges = List.copyOf(ranges);
+        } else {
+            languageRanges = Collections.emptyList();
+        }
+    }
 
     /**
      * Gets the output stream to receive any instructioons or additional information after
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java
index 054f18429..9c8bc91f5 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java
@@ -24,6 +24,9 @@ import java.net.URL;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 
@@ -33,6 +36,8 @@ import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Strings;
+
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -73,6 +78,9 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
     /** Suffix of property for module post-disable message. */
     @Nonnull @NotEmpty public static final String MODULE_POSTDISABLE_PROPERTY = ".postdisable";
 
+    /** Suffix of property for module languages. */
+    @Nonnull @NotEmpty public static final String MODULE_LANGS_PROPERTY = ".langs";
+
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(PropertyDrivenIdPModule.class);
 
@@ -88,6 +96,9 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
     /** Module URL. */
     @Nullable private URL moduleURL;
     
+    /** Available message locales. */
+    @Nonnull @NonnullElements private List<String> locales;
+    
     /** Whether to require an HTTP client. */
     private boolean requireHttpClient;
 
@@ -113,6 +124,7 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
      */
     public PropertyDrivenIdPModule(@Nonnull final InputStream inputStream)
             throws IOException, ModuleException {
+        locales = Collections.emptyList();
         moduleProperties = new Properties();
         moduleProperties.load(inputStream);
         load();
@@ -126,6 +138,7 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
      * @throws ModuleException if the module is not in a valid state
      */
     public PropertyDrivenIdPModule(@Nonnull final Properties properties) throws ModuleException {
+        locales = Collections.emptyList();
         moduleProperties = Constraint.isNotNull(properties, "Properties cannot be null");
         load();
     }
@@ -145,6 +158,9 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
                 moduleURL = new URL(url);
             }
             
+            locales = StringSupport.stringToList(
+                    moduleProperties.getProperty(getId() + MODULE_LANGS_PROPERTY, ""), ", ");
+            
             final Collection<BasicModuleResource> resources = new ArrayList<>();
             
             for (Integer rnum = 1; ; ++rnum) {
@@ -190,12 +206,30 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
     }
 
     /** {@inheritDoc} */
-    @Nonnull @NotEmpty public String getName() {
+    @Nonnull @NotEmpty public String getName(@Nullable final ModuleContext moduleContext) {
+        
+        if (moduleContext != null) {
+            final String best = Locale.lookupTag(moduleContext.getLanguageRanges(), locales);
+            if (best != null && !best.equals(locales.get(0))) {
+                return moduleProperties.getProperty(getId() + MODULE_NAME_PROPERTY + "." + best, moduleName);
+            }
+        }
         return moduleName;
     }
     
     /** {@inheritDoc} */
-    @Nullable @NotEmpty public String getDescription() {
+    @Nullable @NotEmpty public String getDescription(@Nullable final ModuleContext moduleContext) {
+
+        if (moduleContext != null) {
+            final String best = Locale.lookupTag(moduleContext.getLanguageRanges(), locales);
+            if (best != null && !best.equals(locales.get(0))) {
+                final String desc = moduleProperties.getProperty(getId() + MODULE_DESC_PROPERTY + "." + best);
+                if (!Strings.isNullOrEmpty(desc)) {
+                    return desc;
+                }
+            }
+        }
+        
         return StringSupport.trimOrNull(moduleProperties.getProperty(getId() + MODULE_DESC_PROPERTY));
     }
 
@@ -216,7 +250,18 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
         final Map<ModuleResource,ResourceResult> results = super.enable(moduleContext);
         
         if (moduleContext.getMessageStream() != null) {
-            final String msg = moduleProperties.getProperty(getId() + MODULE_POSTENABLE_PROPERTY);
+            
+            String msg = null;
+            
+            final String best = Locale.lookupTag(moduleContext.getLanguageRanges(), locales);
+            if (best != null && !best.equals(locales.get(0))) {
+                msg = moduleProperties.getProperty(getId() + MODULE_POSTENABLE_PROPERTY + "." + best);
+            }
+            
+            if (msg == null) {
+                msg = moduleProperties.getProperty(getId() + MODULE_POSTENABLE_PROPERTY);
+            }
+            
             if (msg != null) {
                 moduleContext.getMessageStream().println(msg);
             }
@@ -232,7 +277,18 @@ public class PropertyDrivenIdPModule extends AbstractIdPModule {
         final Map<ModuleResource,ResourceResult> results = super.disable(moduleContext, clean);
 
         if (moduleContext.getMessageStream() != null) {
-            final String msg = moduleProperties.getProperty(getId() + MODULE_POSTDISABLE_PROPERTY);
+            
+            String msg = null;
+            
+            final String best = Locale.lookupTag(moduleContext.getLanguageRanges(), locales);
+            if (best != null && !best.equals(locales.get(0))) {
+                msg = moduleProperties.getProperty(getId() + MODULE_POSTDISABLE_PROPERTY + "." + best);
+            }
+            
+            if (msg == null) {
+                msg = moduleProperties.getProperty(getId() + MODULE_POSTDISABLE_PROPERTY);
+            }
+
             if (msg != null) {
                 moduleContext.getMessageStream().println(msg);
             }
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java b/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
index 219fc691e..99f8aa21c 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
@@ -28,6 +28,7 @@ import java.nio.file.attribute.BasicFileAttributes;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.Iterator;
+import java.util.Locale.LanguageRange;
 import java.util.Optional;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
@@ -141,7 +142,7 @@ public class IdPModuleTest {
     @Test
     public void testModule() {
         Assert.assertEquals(testModule.getId(), "idp.test");
-        Assert.assertEquals(testModule.getName(), "Test module");
+        Assert.assertEquals(testModule.getName(null), "Test module");
         Assert.assertEquals(testModule.getURL().toString(), "https://wiki.shibboleth.net/confluence/display/IDP4/Home");
         
         final Iterator<ModuleResource> resources = testModule.getResources().iterator();
@@ -155,6 +156,18 @@ public class IdPModuleTest {
         Assert.assertEquals(resource.getSource(),
                 RepositorySupport.buildHTTPSResourceURL("java-identity-provider", "idp-admin-api/src/test/resources/net/shibboleth/idp/module/test.vm"));
         Assert.assertEquals(resource.getDestination(), Path.of("views/test.vm"));
+        
+        context.setLanguageRanges(LanguageRange.parse("fr, de"));
+        Assert.assertEquals(testModule.getName(context), "Test module (French)");
+
+        context.setLanguageRanges(LanguageRange.parse("de, en"));
+        Assert.assertEquals(testModule.getName(context), "Test module (German)");
+
+        context.setLanguageRanges(LanguageRange.parse("en, de"));
+        Assert.assertEquals(testModule.getName(context), "Test module");
+
+        context.setLanguageRanges(LanguageRange.parse("en, en-GB"));
+        Assert.assertEquals(testModule.getName(context), "Test module");
     }
 
     @Test
diff --git a/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties b/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties
index a4012fef4..eb7096037 100644
--- a/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties
+++ b/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties
@@ -3,7 +3,10 @@
 # Main test module
 
 net.shibboleth.idp.module.TestModule = idp.test
+idp.test.langs = en,fr,de
 idp.test.name = Test module
+idp.test.name.fr = Test module (French)
+idp.test.name.de = Test module (German)
 idp.test.desc = Module for unit tests
 idp.test.url = https://wiki.shibboleth.net/confluence/display/IDP4/Home
 
diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/ModuleManagerCLI.java b/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/ModuleManagerCLI.java
index 98fc6f912..d56d169c8 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/ModuleManagerCLI.java
+++ b/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/ModuleManagerCLI.java
@@ -97,6 +97,7 @@ public final class ModuleManagerCLI extends AbstractIdPHomeAwareCommandLine<Modu
                     new ModuleContext(getApplicationContext().getEnvironment().getProperty("idp.home"));
             moduleContext.setHttpClient(getHttpClient());
             moduleContext.setHttpClientSecurityParameters(getHttpClientSecurityParameters());
+            moduleContext.setLanguageRanges(args.getLanguageRanges());
             
             if (args.getList() || !args.getInfoModuleIds().isEmpty()) {
                 doList(moduleContext, args);
@@ -128,8 +129,8 @@ public final class ModuleManagerCLI extends AbstractIdPHomeAwareCommandLine<Modu
                 if (args.getInfoModuleIds().contains(module.getId())) {
                     System.out.println();
                     System.out.println("Module: " + module.getId());
-                    System.out.println("\tName: " + module.getName());
-                    System.out.println("\tDesc: " + module.getDescription());
+                    System.out.println("\tName: " + module.getName(moduleContext));
+                    System.out.println("\tDesc: " + module.getDescription(moduleContext));
                     System.out.println("\tHelp: " + module.getURL());
                     if (module.isEnabled(moduleContext)) {
                         System.out.println("\tStatus: " + ANSIColors.ANSI_GREEN + "ENABLED" + ANSIColors.ANSI_RESET);
diff --git a/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp b/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp
index d33fa9cfa..b09b29268 100644
--- a/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp
+++ b/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp
@@ -52,7 +52,7 @@ final ModuleContext moduleContext =
     new ModuleContext(((Environment) request.getAttribute("environment")).getProperty("idp.home"));
 for (final IdPModule module : ServiceLoader.load(IdPModule.class)) {
     if (module.isEnabled(moduleContext)) {
-        out.println("\t" + module.getId() + " (" + module.getName() + ")");
+        out.println("\t" + module.getId() + " (" + module.getName(moduleContext) + ")");
     }
 }
 out.println();

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


More information about the commits mailing list