Browse Source

Merge branch 'master' into enh-domain

Jason Rivard 4 years ago
parent
commit
95ab2ed200

+ 1 - 1
client/pom.xml

@@ -80,7 +80,7 @@
             <plugin>
                 <groupId>com.github.eirslett</groupId>
                 <artifactId>frontend-maven-plugin</artifactId>
-                <version>1.10.3</version>
+                <version>1.11.0</version>
                 <configuration>
                     <nodeVersion>${node.version}</nodeVersion>
                     <npmVersion>${npm.version}</npmVersion>

+ 1 - 1
docker/pom.xml

@@ -33,7 +33,7 @@
             <plugin>
                 <groupId>com.google.cloud.tools</groupId>
                 <artifactId>jib-maven-plugin</artifactId>
-                <version>2.6.0</version>
+                <version>2.7.0</version>
                 <executions>
                     <execution>
                         <id>make-docker-image</id>

+ 3 - 3
pom.xml

@@ -235,7 +235,7 @@
                     <dependency>
                         <groupId>com.puppycrawl.tools</groupId>
                         <artifactId>checkstyle</artifactId>
-                        <version>8.37</version>
+                        <version>8.38</version>
                     </dependency>
                 </dependencies>
                 <executions>
@@ -427,13 +427,13 @@
         <dependency>
             <groupId>org.openjdk.jmh</groupId>
             <artifactId>jmh-core</artifactId>
-            <version>1.26</version>
+            <version>1.27</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.openjdk.jmh</groupId>
             <artifactId>jmh-generator-annprocess</artifactId>
-            <version>1.26</version>
+            <version>1.27</version>
             <scope>test</scope>
         </dependency>
 

+ 4 - 4
server/pom.xml

@@ -291,12 +291,12 @@
         <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15on</artifactId>
-            <version>1.67</version>
+            <version>1.68</version>
         </dependency>
         <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcpkix-jdk15on</artifactId>
-            <version>1.67</version>
+            <version>1.68</version>
         </dependency>
         <dependency>
             <groupId>jaxen</groupId>
@@ -321,7 +321,7 @@
         <dependency>
             <groupId>com.blueconic</groupId>
             <artifactId>browscap-java</artifactId>
-            <version>1.3.2</version>
+            <version>1.3.3</version>
         </dependency>
         <dependency>
             <groupId>org.jetbrains.xodus</groupId>
@@ -342,7 +342,7 @@
         <dependency>
             <groupId>com.github.ben-manes.caffeine</groupId>
             <artifactId>caffeine</artifactId>
-            <version>2.8.6</version>
+            <version>2.8.8</version>
         </dependency>
         <dependency>
             <groupId>com.nulab-inc</groupId>

+ 62 - 43
server/src/main/java/password/pwm/PwmApplication.java

@@ -102,6 +102,7 @@ import java.security.KeyStore;
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -111,7 +112,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
 import java.util.function.Supplier;
-import java.util.stream.Collectors;
 
 public class PwmApplication
 {
@@ -163,50 +163,10 @@ public class PwmApplication
 
         runtimeNonce = PwmRandom.getInstance().randomUUID().toString();
 
-        this.domains = this.pwmEnvironment.getConfig().getDomainIDs().stream()
-                .collect( Collectors.toUnmodifiableMap(
-                        ( domainID ) -> domainID,
-                        ( domainID ) -> new PwmDomain( this, domainID ) ) );
-
+        this.domains = Initializer.initializeDomains( this );
 
         // initialize log4j
-        if ( !pwmEnvironment.isInternalRuntimeInstance() && !pwmEnvironment.getFlags().contains( PwmEnvironment.ApplicationFlag.CommandLineInstance ) )
-        {
-            final String log4jFileName = pwmEnvironment.getConfig().readSettingAsString( PwmSetting.EVENTS_JAVA_LOG4JCONFIG_FILE );
-            final File log4jFile = FileSystemUtility.figureFilepath( log4jFileName, pwmEnvironment.getApplicationPath() );
-            final String consoleLevel;
-            final String fileLevel;
-
-            switch ( getApplicationMode() )
-            {
-                case ERROR:
-                case NEW:
-                    consoleLevel = PwmLogLevel.TRACE.toString();
-                    fileLevel = PwmLogLevel.TRACE.toString();
-                    break;
-
-                default:
-                    consoleLevel = pwmEnvironment.getConfig().readSettingAsString( PwmSetting.EVENTS_JAVA_STDOUT_LEVEL );
-                    fileLevel = pwmEnvironment.getConfig().readSettingAsString( PwmSetting.EVENTS_FILE_LEVEL );
-                    break;
-            }
-
-            PwmLogManager.initializeLogger( this.getDefaultDomain(), getDefaultDomain().getConfig(), log4jFile, consoleLevel, pwmEnvironment.getApplicationPath(), fileLevel );
-
-            switch ( getApplicationMode() )
-            {
-                case RUNNING:
-                    break;
-
-                case ERROR:
-                    LOGGER.fatal( () -> "starting up in ERROR mode! Check log or health check information for cause" );
-                    break;
-
-                default:
-                    LOGGER.trace( () -> "setting log level to TRACE because application mode is " + getApplicationMode() );
-                    break;
-            }
-        }
+        Initializer.initializeLogging( this );
 
         // get file lock
         if ( !pwmEnvironment.isInternalRuntimeInstance() )
@@ -1012,7 +972,66 @@ public class PwmApplication
             }
         }
 
+        public static Map<DomainID, PwmDomain> initializeDomains( final PwmApplication pwmApplication )
+        {
+            final Map<DomainID, PwmDomain> domainMap = new LinkedHashMap<>();
+            for ( final DomainID domainID : pwmApplication.getPwmEnvironment().getConfig().getDomainIDs() )
+            {
+                final PwmDomain newDomain = new PwmDomain( pwmApplication, domainID );
+                domainMap.put( domainID, newDomain );
+            }
 
+            return Collections.unmodifiableMap( domainMap );
+        }
+
+        public static void initializeLogging( final PwmApplication pwmApplication )
+        {
+            final PwmEnvironment pwmEnvironment = pwmApplication.getPwmEnvironment();
+
+            if ( !pwmEnvironment.isInternalRuntimeInstance() && !pwmEnvironment.getFlags().contains( PwmEnvironment.ApplicationFlag.CommandLineInstance ) )
+            {
+                final String log4jFileName = pwmEnvironment.getConfig().readSettingAsString( PwmSetting.EVENTS_JAVA_LOG4JCONFIG_FILE );
+                final File log4jFile = FileSystemUtility.figureFilepath( log4jFileName, pwmEnvironment.getApplicationPath() );
+                final String consoleLevel;
+                final String fileLevel;
+
+                switch ( pwmApplication.getApplicationMode() )
+                {
+                    case ERROR:
+                    case NEW:
+                        consoleLevel = PwmLogLevel.TRACE.toString();
+                        fileLevel = PwmLogLevel.TRACE.toString();
+                        break;
+
+                    default:
+                        consoleLevel = pwmEnvironment.getConfig().readSettingAsString( PwmSetting.EVENTS_JAVA_STDOUT_LEVEL );
+                        fileLevel = pwmEnvironment.getConfig().readSettingAsString( PwmSetting.EVENTS_FILE_LEVEL );
+                        break;
+                }
+
+                PwmLogManager.initializeLogger(
+                        pwmApplication.getDefaultDomain(),
+                        pwmApplication.getDefaultDomain().getConfig(),
+                        log4jFile,
+                        consoleLevel,
+                        pwmEnvironment.getApplicationPath(),
+                        fileLevel );
+
+                switch ( pwmApplication.getApplicationMode() )
+                {
+                    case RUNNING:
+                        break;
+
+                    case ERROR:
+                        LOGGER.fatal( () -> "starting up in ERROR mode! Check log or health check information for cause" );
+                        break;
+
+                    default:
+                        LOGGER.trace( () -> "setting log level to TRACE because application mode is " + pwmApplication.getApplicationMode() );
+                        break;
+                }
+            }
+        }
     }
 
     public File getTempDirectory( ) throws PwmUnrecoverableException

+ 1 - 1
server/src/main/java/password/pwm/PwmConstants.java

@@ -94,7 +94,7 @@ public abstract class PwmConstants
     public static final String PROFILE_ID_ALL = "all";
     public static final String PROFILE_ID_DEFAULT = "default";
 
-    public static final String DOMAIN_ID_DEFAULT = "default";
+    public static final DomainID DOMAIN_ID_DEFAULT = DomainID.create( "default" );
     public static final DomainID DOMAIN_ID_PLACEHOLDER = DomainID.create( "default" );
 
     public static final String TOKEN_KEY_PWD_CHG_DATE = "_lastPwdChange";

+ 5 - 0
server/src/main/java/password/pwm/bean/DomainID.java

@@ -82,6 +82,11 @@ public class DomainID implements Comparable<DomainID>, Serializable
         return domainID;
     }
 
+    public String stringValue()
+    {
+        return domainID;
+    }
+
     public static DomainID systemId()
     {
         return SYSTEM_DOMAIN_ID;

+ 8 - 3
server/src/main/java/password/pwm/config/AppConfig.java

@@ -59,6 +59,7 @@ public class AppConfig
     private final StoredConfiguration storedConfiguration;
     private final SettingReader settingReader;
     private final Map<DomainID, DomainConfig> domainConfigMap;
+    private final List<DomainID> domainIDList;
 
     private PwmSecurityKey tempInstanceKey = null;
 
@@ -66,7 +67,12 @@ public class AppConfig
     {
         this.storedConfiguration = storedConfiguration;
         this.settingReader = new SettingReader( storedConfiguration, null, DomainID.systemId() );
-        domainConfigMap = getDomainIDs().stream()
+
+        this.domainIDList = settingReader.readSettingAsStringArray( PwmSetting.DOMAIN_LIST ).stream()
+                .map( DomainID::create )
+                .collect( Collectors.toUnmodifiableList() );
+
+        this.domainConfigMap = domainIDList.stream()
                 .collect( Collectors.toUnmodifiableMap(
                         ( domainID ) -> domainID,
                         ( domainID ) -> new DomainConfig( this, domainID ) ) );
@@ -74,8 +80,7 @@ public class AppConfig
 
     public List<DomainID> getDomainIDs()
     {
-        final List<String> strings = settingReader.readSettingAsStringArray( PwmSetting.DOMAIN_LIST );
-        return strings.stream().map( DomainID::create ).collect( Collectors.toUnmodifiableList() );
+        return domainIDList;
     }
 
     public Map<DomainID, DomainConfig> getDomainConfigs()

+ 6 - 2
server/src/main/java/password/pwm/config/ConfigurationUtil.java

@@ -22,6 +22,8 @@ package password.pwm.config;
 
 import password.pwm.config.option.DataStorageMethod;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -35,7 +37,9 @@ public class ConfigurationUtil
 
     public static List<DataStorageMethod> getCrReadPreference( final DomainConfig domainConfig )
     {
-        final List<DataStorageMethod> readPreferences = domainConfig.getResponseStorageLocations( PwmSetting.FORGOTTEN_PASSWORD_READ_PREFERENCE );
+        final List<DataStorageMethod> readPreferences = new ArrayList<>(
+                domainConfig.getResponseStorageLocations( PwmSetting.FORGOTTEN_PASSWORD_READ_PREFERENCE ) );
+
         if ( readPreferences.size() == 1 && readPreferences.iterator().next() == DataStorageMethod.AUTO )
         {
             readPreferences.clear();
@@ -55,7 +59,7 @@ public class ConfigurationUtil
             readPreferences.add( DataStorageMethod.NMAS );
         }
 
-        return readPreferences;
+        return Collections.unmodifiableList( readPreferences );
     }
 
     public static List<DataStorageMethod> getCrWritePreference( final DomainConfig domainConfig )

+ 12 - 9
server/src/main/java/password/pwm/config/stored/StoredConfigItemKey.java

@@ -69,14 +69,17 @@ public class StoredConfigItemKey implements Serializable, Comparable<StoredConfi
 
     private static final long serialVersionUID = 1L;
 
-    private StoredConfigItemKey( final RecordType recordType, final DomainID domainID, final String recordID, final String profileID )
+    private StoredConfigItemKey(
+            final RecordType recordType,
+            final DomainID domainID,
+            final String recordID,
+            final String profileID
+    )
     {
-        Objects.requireNonNull( recordType, "recordType can not be null" );
-        Objects.requireNonNull( recordID, "recordID can not be null" );
+        this.recordType = Objects.requireNonNull( recordType, "recordType can not be null" );
+        this.recordID = Objects.requireNonNull( recordID, "recordID can not be null" );
+        this.domainID = Objects.requireNonNull( domainID, "domainID can not be null" );
 
-        this.recordType = recordType;
-        this.domainID = domainID;
-        this.recordID = recordID;
         this.profileID = profileID;
     }
 
@@ -102,7 +105,7 @@ public class StoredConfigItemKey implements Serializable, Comparable<StoredConfi
 
     public static StoredConfigItemKey fromSetting( final PwmSetting pwmSetting, final String profileID )
     {
-        return new StoredConfigItemKey( RecordType.SETTING, null, pwmSetting.getKey(), profileID );
+        return new StoredConfigItemKey( RecordType.SETTING, PwmConstants.DOMAIN_ID_PLACEHOLDER, pwmSetting.getKey(), profileID );
     }
 
     public static StoredConfigItemKey fromSetting( final PwmSetting pwmSetting, final String profileID, final DomainID domainID )
@@ -112,12 +115,12 @@ public class StoredConfigItemKey implements Serializable, Comparable<StoredConfi
 
     static StoredConfigItemKey fromLocaleBundle( final PwmLocaleBundle localeBundle, final String key )
     {
-        return new StoredConfigItemKey( RecordType.LOCALE_BUNDLE, null, localeBundle.getKey(), key );
+        return new StoredConfigItemKey( RecordType.LOCALE_BUNDLE, PwmConstants.DOMAIN_ID_PLACEHOLDER, localeBundle.getKey(), key );
     }
 
     static StoredConfigItemKey fromConfigurationProperty( final ConfigurationProperty configurationProperty )
     {
-        return new StoredConfigItemKey( RecordType.PROPERTY, null, configurationProperty.getKey(), null );
+        return new StoredConfigItemKey( RecordType.PROPERTY, DomainID.systemId(), configurationProperty.getKey(), null );
     }
 
     public boolean isRecordType( final RecordType recordType )

+ 37 - 15
server/src/main/java/password/pwm/config/stored/StoredConfigXmlSerializer.java

@@ -57,6 +57,7 @@ import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Queue;
 import java.util.ResourceBundle;
@@ -237,7 +238,7 @@ public class StoredConfigXmlSerializer implements StoredConfigSerializer
                 return DomainID.systemId();
             }
 
-            final String domainID = xmlElement.getAttributeValue( StoredConfigXmlConstants.XML_ATTRIBUTE_DOMAIN ).orElse( PwmConstants.DOMAIN_ID_DEFAULT );
+            final String domainID = xmlElement.getAttributeValue( StoredConfigXmlConstants.XML_ATTRIBUTE_DOMAIN ).orElse( PwmConstants.DOMAIN_ID_DEFAULT.stringValue() );
             return DomainID.create( domainID );
         }
 
@@ -468,10 +469,12 @@ public class StoredConfigXmlSerializer implements StoredConfigSerializer
             {
                 final PwmSetting pwmSetting = storedConfigItemKey.toPwmSetting();
                 final String profileID = storedConfigItemKey.getProfileID();
-                final StoredValue storedValue = storedConfiguration.readSetting( pwmSetting, profileID );
-                final XmlElement settingElement = makeSettingXmlElement( storedConfiguration, pwmSetting, profileID, storedValue, xmlOutputProcessData );
-                decorateElementWithMetaData( storedConfiguration, StoredConfigItemKey.fromSetting( pwmSetting, profileID ), settingElement );
-                settingsElement.addContent( settingElement );
+                storedConfiguration.readStoredValue( storedConfigItemKey ).ifPresent( ( storedValue ->
+                {
+                    final XmlElement settingElement = makeSettingXmlElement( storedConfiguration, storedConfigItemKey, storedValue, xmlOutputProcessData );
+                    decorateElementWithMetaData( storedConfiguration, StoredConfigItemKey.fromSetting( pwmSetting, profileID ), settingElement );
+                    settingsElement.addContent( settingElement );
+                } ) );
             };
 
             StoredConfigurationUtil.allPossibleSettingKeysForConfiguration( storedConfiguration )
@@ -511,15 +514,21 @@ public class StoredConfigXmlSerializer implements StoredConfigSerializer
 
         static XmlElement makeSettingXmlElement(
                 final StoredConfiguration storedConfiguration,
-                final PwmSetting pwmSetting,
-                final String profileID,
+                final StoredConfigItemKey key,
                 final StoredValue storedValue,
                 final XmlOutputProcessData xmlOutputProcessData
         )
         {
+            Objects.requireNonNull( storedValue );
+
+            final PwmSetting pwmSetting = key.toPwmSetting();
+            final String profileID = key.getProfileID();
+
             final XmlFactory xmlFactory = XmlFactory.getFactory();
 
             final XmlElement settingElement = xmlFactory.newElement( StoredConfigXmlConstants.XML_ELEMENT_SETTING );
+
+
             settingElement.setAttribute( StoredConfigXmlConstants.XML_ATTRIBUTE_KEY, pwmSetting.getKey() );
 
             if ( !StringUtil.isEmpty( profileID ) )
@@ -546,11 +555,25 @@ public class StoredConfigXmlSerializer implements StoredConfigSerializer
                 valueElements.addAll( storedValue.toXmlValues( StoredConfigXmlConstants.XML_ELEMENT_VALUE, xmlOutputProcessData ) );
             }
 
+            decorateElementWithDomain( storedConfiguration, key, settingElement );
             settingElement.setAttribute( StoredConfigXmlConstants.XML_ATTRIBUTE_SYNTAX_VERSION, String.valueOf( storedValue.currentSyntaxVersion() ) );
             settingElement.addContent( valueElements );
             return settingElement;
         }
 
+        private static void decorateElementWithDomain(
+                final StoredConfiguration storedConfiguration,
+                final StoredConfigItemKey key,
+                final XmlElement xmlElement
+        )
+        {
+            final DomainID domainID = key.getDomainID();
+            if ( !domainID.isSystem() || StoredConfigurationUtil.domainList( storedConfiguration ).size() > 1 )
+            {
+                xmlElement.setAttribute( StoredConfigXmlConstants.XML_ATTRIBUTE_DOMAIN, domainID.stringValue() );
+            }
+        }
+
         private static void decorateElementWithMetaData(
                 final StoredConfiguration storedConfiguration,
                 final StoredConfigItemKey key,
@@ -769,10 +792,11 @@ public class StoredConfigXmlSerializer implements StoredConfigSerializer
 
                 final PwmSecurityKey pwmSecurityKey = inputDocumentReader.getKey();
 
+                final StoredConfigItemKey key = StoredConfigItemKey.fromSetting( pwmSetting, null, PwmConstants.DOMAIN_ID_DEFAULT );
+
                 final XmlElement settingElement = StoredConfigXmlSerializer.XmlOutputHandler.makeSettingXmlElement(
                         null,
-                        pwmSetting,
-                        null,
+                        key,
                         new StringValue( stringValue ),
                         XmlOutputProcessData.builder().storedValueEncoderMode( StoredValueEncoder.Mode.PLAIN ).pwmSecurityKey( pwmSecurityKey ).build() );
                 final Optional<XmlElement> settingsElement = xmlDocument.getRootElement().getChild( StoredConfigXmlConstants.XML_ELEMENT_SETTING );
@@ -839,17 +863,15 @@ public class StoredConfigXmlSerializer implements StoredConfigSerializer
             {
                 final StoredConfigXmlSerializer.XmlInputDocumentReader inputDocumentReader = new StoredConfigXmlSerializer.XmlInputDocumentReader( xmlDocument );
 
-                {
-                    final Optional<XmlElement> existingAppPropertySetting = inputDocumentReader.xpathForSetting( PwmSetting.APP_PROPERTY_OVERRIDES, null );
-                    existingAppPropertySetting.ifPresent( XmlElement::detach );
-                }
+                inputDocumentReader.xpathForSetting( PwmSetting.APP_PROPERTY_OVERRIDES, null ).ifPresent( XmlElement::detach );
 
                 final PwmSecurityKey pwmSecurityKey = inputDocumentReader.getKey();
 
+                final StoredConfigItemKey key = StoredConfigItemKey.fromSetting( PwmSetting.APP_PROPERTY_OVERRIDES, null, PwmConstants.DOMAIN_ID_DEFAULT );
+
                 final XmlElement settingElement = StoredConfigXmlSerializer.XmlOutputHandler.makeSettingXmlElement(
                         null,
-                        PwmSetting.APP_PROPERTY_OVERRIDES,
-                        null,
+                        key,
                         new StringArrayValue( newValues ),
                         XmlOutputProcessData.builder().storedValueEncoderMode( StoredValueEncoder.Mode.PLAIN ).pwmSecurityKey( pwmSecurityKey ).build() );
                 final Optional<XmlElement> settingsElement = xmlDocument.getRootElement().getChild( StoredConfigXmlConstants.XML_ELEMENT_SETTING );

+ 9 - 0
server/src/main/java/password/pwm/config/stored/StoredConfigurationUtil.java

@@ -21,6 +21,7 @@
 package password.pwm.config.stored;
 
 import password.pwm.PwmConstants;
+import password.pwm.bean.DomainID;
 import password.pwm.bean.UserIdentity;
 import password.pwm.config.AppConfig;
 import password.pwm.config.PwmSetting;
@@ -467,4 +468,12 @@ public abstract class StoredConfigurationUtil
 
         throw new IllegalStateException();
     }
+
+    public static List<String> domainList( final StoredConfiguration storedConfiguration )
+    {
+        final StoredConfigItemKey domainListKey = StoredConfigItemKey.fromSetting( PwmSetting.DOMAIN_LIST, null, DomainID.systemId() );
+        final StoredValue storedStringArray = getValueOrDefault( storedConfiguration, domainListKey );
+        final List<String> domainList = ValueTypeConverter.valueToStringArray( storedStringArray );
+        return Collections.unmodifiableList( domainList );
+    }
 }

+ 4 - 4
server/src/main/java/password/pwm/error/PwmException.java

@@ -24,23 +24,23 @@ public abstract class PwmException extends Exception
 {
     protected final ErrorInformation errorInformation;
 
-    public PwmException( final ErrorInformation error )
+    protected PwmException( final ErrorInformation error )
     {
         this.errorInformation = error == null ? new ErrorInformation( PwmError.ERROR_INTERNAL ) : error;
     }
 
-    public PwmException( final ErrorInformation error, final Throwable initialCause )
+    protected PwmException( final ErrorInformation error, final Throwable initialCause )
     {
         this.errorInformation = error == null ? new ErrorInformation( PwmError.ERROR_INTERNAL ) : error;
         this.initCause( initialCause );
     }
 
-    public PwmException( final PwmError error )
+    protected PwmException( final PwmError error )
     {
         this.errorInformation = new ErrorInformation( error );
     }
 
-    public PwmException( final PwmError error, final String detailedErrorMsg )
+    protected PwmException( final PwmError error, final String detailedErrorMsg )
     {
         this.errorInformation = new ErrorInformation( error, detailedErrorMsg );
     }

+ 2 - 0
server/src/main/java/password/pwm/http/servlet/configeditor/data/SettingDataMaker.java

@@ -27,6 +27,7 @@ import password.pwm.config.PwmSettingCategory;
 import password.pwm.config.PwmSettingTemplateSet;
 import password.pwm.config.stored.StoredConfiguration;
 import password.pwm.config.stored.StoredConfigurationFactory;
+import password.pwm.config.stored.StoredConfigurationUtil;
 import password.pwm.config.value.ValueTypeConverter;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.i18n.PwmLocaleBundle;
@@ -91,6 +92,7 @@ public class SettingDataMaker
 
         final VarData varMap = VarData.builder()
                 .ldapProfileIds( ValueTypeConverter.valueToStringArray( storedConfiguration.readSetting( PwmSetting.LDAP_PROFILE_LIST, null ) ) )
+                .domainIds( StoredConfigurationUtil.domainList( storedConfiguration ) )
                 .currentTemplate( templateSet )
                 .build();
 

+ 1 - 0
server/src/main/java/password/pwm/http/servlet/configeditor/data/VarData.java

@@ -32,5 +32,6 @@ import java.util.List;
 public class VarData implements Serializable
 {
     private final List<String> ldapProfileIds;
+    private final List<String> domainIds;
     private final PwmSettingTemplateSet currentTemplate;
 }

+ 3 - 3
server/src/main/java/password/pwm/i18n/PwmLocaleBundle.java

@@ -50,12 +50,12 @@ public enum PwmLocaleBundle
         AdminOnly,
     }
 
-    private final Flag[] flags;
+    private final Set<Flag> flags;
 
     PwmLocaleBundle( final Class<? extends PwmDisplayBundle> theClass, final Flag... flags )
     {
         this.theClass = theClass;
-        this.flags = flags;
+        this.flags = JavaHelper.enumSetFromArray( flags );
     }
 
     public Class<? extends PwmDisplayBundle> getTheClass( )
@@ -65,7 +65,7 @@ public enum PwmLocaleBundle
 
     public boolean isAdminOnly( )
     {
-        return JavaHelper.enumArrayContainsValue( flags, Flag.AdminOnly );
+        return flags.contains( Flag.AdminOnly );
     }
 
     public static Optional<PwmLocaleBundle> forKey( final String key )

+ 1 - 1
server/src/main/java/password/pwm/util/java/LicenseInfoReader.java

@@ -42,7 +42,7 @@ public class LicenseInfoReader
     {
         final List<String> attributionFiles = Collections.singletonList( "/attribution.xml" );
         final List<DependencyInfo> returnList = new ArrayList<>();
-        final XmlFactory factory = new XmlFactory.XmlFactoryW3c();
+        final XmlFactory factory = XmlFactory.getFactory();
 
         for ( final String attributionFile : attributionFiles )
         {

+ 8 - 2
server/src/main/java/password/pwm/util/java/XmlFactory.java

@@ -64,17 +64,23 @@ public interface XmlFactory
 
     static XmlFactory getFactory()
     {
-        return new XmlFactoryW3c();
+        return XmlFactoryW3c.getW3cFactory();
     }
 
     class XmlFactoryW3c implements XmlFactory
     {
+        private static final XmlFactory W3C_FACTORY = new XmlFactoryW3c();
         private static final Charset STORAGE_CHARSET = StandardCharsets.UTF_8;
 
-        XmlFactoryW3c()
+        private XmlFactoryW3c()
         {
         }
 
+        static XmlFactory getW3cFactory()
+        {
+            return W3C_FACTORY;
+        }
+
         @Override
         public XmlDocument parseXml( final InputStream inputStream )
                 throws PwmUnrecoverableException

+ 2 - 2
server/src/test/java/password/pwm/util/java/AtomicLoopIntIncrementerTest.java

@@ -36,13 +36,13 @@ public class AtomicLoopIntIncrementerTest
             Assert.assertEquals( i, next );
         }
 
-        Assert.assertEquals( atomicLoopIntIncrementer.next(), 0 );
+        Assert.assertEquals( 0,  atomicLoopIntIncrementer.next() );
 
         for ( int i = 0; i < 5; i++ )
         {
             atomicLoopIntIncrementer.next();
         }
 
-        Assert.assertEquals( atomicLoopIntIncrementer.next(), 1 );
+        Assert.assertEquals( 1,  atomicLoopIntIncrementer.next() );
     }
 }

+ 1 - 1
server/src/test/java/password/pwm/util/localdb/LocalDBLoggerExtendedTest.java

@@ -257,7 +257,7 @@ public class LocalDBLoggerExtendedTest
     private static class RandomValueMaker
     {
         private int outputLength;
-        final StringBuffer randomValue = new StringBuffer();
+        final StringBuilder randomValue = new StringBuilder();
         final Random random = new Random();
 
         RandomValueMaker( final int outputLength )

+ 4 - 0
webapp/src/main/webapp/WEB-INF/jsp/configeditor.jsp

@@ -45,6 +45,10 @@
     <div class="configeditor-header" id="header" >
         <div id="header-center-wide" style="min-width: 850px">
             <div id="header-title">
+                <select>
+                    <option value="system">System</option>
+                    <option value="default">Domain: Default</option>
+                </select>
                 <span id="currentPageDisplay"></span>
                 <span style="visibility: hidden" id="working_icon" class="headerIcon pwm-icon pwm-icon-cog pwm-icon-spin"></span>
 

+ 7 - 0
webapp/src/main/webapp/public/resources/js/configeditor.js

@@ -121,6 +121,7 @@ PWM_CFGEDIT.readSetting = function(keyName, valueWriter) {
     if (PWM_CFGEDIT.readCurrentProfile()) {
         url = PWM_MAIN.addParamToUrl(url, 'profile', PWM_CFGEDIT.readCurrentProfile());
     }
+    url = PWM_MAIN.addParamToUrl(url, 'domain', PWM_CFGEDIT.readCurrentDomain());
     var loadFunction = function(data) {
         PWM_VAR['outstandingOperations']--;
         PWM_CFGEDIT.handleWorkingIcon();
@@ -185,6 +186,7 @@ PWM_CFGEDIT.writeSetting = function(keyName, valueData, nextAction) {
     if (PWM_CFGEDIT.readCurrentProfile()) {
         url = PWM_MAIN.addParamToUrl(url,'profile',PWM_CFGEDIT.readCurrentProfile());
     }
+    url = PWM_MAIN.addParamToUrl(url, 'domain', PWM_CFGEDIT.readCurrentDomain());
     var loadFunction = function(data) {
         PWM_VAR['outstandingOperations']--;
         PWM_CFGEDIT.handleWorkingIcon();
@@ -1108,6 +1110,7 @@ PWM_CFGEDIT.drawNavigationMenu = function(nextFunction) {
     };
 
     var url = 'editor?processAction=menuTreeData';
+    url = PWM_MAIN.addParamToUrl(url,'domain',PWM_CFGEDIT.readCurrentDomain());
     var filterParams = PWM_CFGEDIT.readNavigationFilters();
 
     PWM_MAIN.ajaxRequest(url,function(data){
@@ -1276,6 +1279,10 @@ PWM_CFGEDIT.readCurrentProfile = function() {
     return PWM_VAR['currentProfile'];
 };
 
+PWM_CFGEDIT.readCurrentDomain = function() {
+    return PWM_VAR['currentDomain'];
+};
+
 PWM_CFGEDIT.setCurrentProfile = function(profile) {
     if (profile) {
         PWM_VAR['currentProfile'] = profile;