Skip to content

Commit 35a19de

Browse files
committed
storedconfig refactoring, switch to non-xml based in-memory config for perf and maintainability
1 parent 34ac4fa commit 35a19de

File tree

125 files changed

+4725
-3222
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+4725
-3222
lines changed

server/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
</goals>
5353
<phase>test</phase>
5454
<configuration>
55+
<trimStackTrace>false</trimStackTrace>
5556
<skipTests>${skipTests}</skipTests>
5657
<excludes>
5758
<exclude>**/ExtendedTest*.java</exclude>

server/src/main/java/password/pwm/PwmApplication.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,16 @@ private void postInitTasks( )
305305
{
306306
final Instant startTime = Instant.now();
307307

308-
pwmEnvironment.getConfig().outputToLog();
308+
try
309+
{
310+
pwmEnvironment.getConfig().outputToLog();
311+
}
312+
catch ( PwmException e )
313+
{
314+
LOGGER.error( "error outputting log to debug: " + e.getMessage() );
315+
}
316+
317+
309318

310319
// detect if config has been modified since previous startup
311320
try

server/src/main/java/password/pwm/PwmConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ public abstract class PwmConstants
101101

102102
public static final String LDAP_AD_PASSWORD_POLICY_CONTROL_ASN = "1.2.840.113556.1.4.2066";
103103
public static final String PROFILE_ID_ALL = "all";
104+
public static final String PROFILE_ID_DEFAULT = "default";
104105

105106
public static final String TOKEN_KEY_PWD_CHG_DATE = "_lastPwdChange";
106107

server/src/main/java/password/pwm/config/Configuration.java

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@
4545
import password.pwm.config.profile.PwmPasswordRule;
4646
import password.pwm.config.profile.SetupOtpProfile;
4747
import password.pwm.config.profile.UpdateProfileProfile;
48-
import password.pwm.config.stored.ConfigurationProperty;
49-
import password.pwm.config.stored.StoredConfigurationImpl;
48+
import password.pwm.config.stored.ComparingChangeLog;
49+
import password.pwm.config.stored.StoredConfigItemKey;
50+
import password.pwm.config.stored.StoredConfiguration;
51+
import password.pwm.config.stored.StoredConfigurationFactory;
5052
import password.pwm.config.stored.StoredConfigurationUtil;
5153
import password.pwm.config.value.BooleanValue;
5254
import password.pwm.config.value.CustomLinkValue;
@@ -70,6 +72,7 @@
7072
import password.pwm.error.ErrorInformation;
7173
import password.pwm.error.PwmError;
7274
import password.pwm.error.PwmUnrecoverableException;
75+
import password.pwm.i18n.PwmLocaleBundle;
7376
import password.pwm.util.PasswordData;
7477
import password.pwm.util.i18n.LocaleHelper;
7578
import password.pwm.util.java.StringUtil;
@@ -78,7 +81,6 @@
7881
import password.pwm.util.secure.PwmRandom;
7982
import password.pwm.util.secure.PwmSecurityKey;
8083

81-
import java.io.Serializable;
8284
import java.lang.reflect.InvocationTargetException;
8385
import java.security.cert.X509Certificate;
8486
import java.util.ArrayList;
@@ -104,13 +106,13 @@ public class Configuration implements SettingReader
104106
{
105107
private static final PwmLogger LOGGER = PwmLogger.forClass( Configuration.class );
106108

107-
private final StoredConfigurationImpl storedConfiguration;
109+
private final StoredConfiguration storedConfiguration;
108110

109111
private DataCache dataCache = new DataCache();
110112

111113
private String cashedConfigurationHash;
112114

113-
public Configuration( final StoredConfigurationImpl storedConfiguration )
115+
public Configuration( final StoredConfiguration storedConfiguration )
114116
{
115117
this.storedConfiguration = storedConfiguration;
116118
}
@@ -126,13 +128,15 @@ public static void deprecatedSettingException( final PwmSetting pwmSetting, fina
126128
}
127129

128130
public void outputToLog( )
131+
throws PwmUnrecoverableException
129132
{
130133
if ( !LOGGER.isEnabled( PwmLogLevel.TRACE ) )
131134
{
132135
return;
133136
}
134137

135-
final Map<String, String> debugStrings = storedConfiguration.getModifiedSettingDebugValues( PwmConstants.DEFAULT_LOCALE, true );
138+
final ComparingChangeLog changeLog = new ComparingChangeLog( StoredConfigurationFactory.newStoredConfiguration(), storedConfiguration );
139+
final Map<String, String> debugStrings = StoredConfigurationUtil.asDebugMap( storedConfiguration, changeLog.changedValues(), PwmConstants.DEFAULT_LOCALE );
136140
final List<Supplier<CharSequence>> outputStrings = new ArrayList<>();
137141

138142
for ( final Map.Entry<String, String> entry : debugStrings.entrySet() )
@@ -516,7 +520,7 @@ public static <E extends Enum<E>> Set<E> valueToOptionList( final PwmSetting set
516520
}
517521
}
518522

519-
public Map<Locale, String> readLocalizedBundle( final String className, final String keyName )
523+
public Map<Locale, String> readLocalizedBundle( final PwmLocaleBundle className, final String keyName )
520524
{
521525
final String key = className + "-" + keyName;
522526
if ( dataCache.customText.containsKey( key ) )
@@ -705,11 +709,6 @@ public Collection<Locale> localesForSetting( final PwmSetting setting )
705709
return returnCollection;
706710
}
707711

708-
public String readProperty( final ConfigurationProperty key )
709-
{
710-
return storedConfiguration.readConfigProperty( key );
711-
}
712-
713712
public boolean readSettingAsBoolean( final PwmSetting setting )
714713
{
715714
return JavaTypeConverter.valueToBoolean( readStoredValue( setting ) );
@@ -748,48 +747,50 @@ public PrivateKeyCertificate readSettingAsPrivateKey( final PwmSetting setting )
748747
return ( PrivateKeyCertificate ) readStoredValue( setting ).toNativeObject();
749748
}
750749

751-
public String getNotes( )
752-
{
753-
return storedConfiguration.readConfigProperty( ConfigurationProperty.NOTES );
754-
}
755-
756750
private PwmSecurityKey tempInstanceKey = null;
757751

758752
public PwmSecurityKey getSecurityKey( ) throws PwmUnrecoverableException
759753
{
760-
final PasswordData configValue = readSettingAsPassword( PwmSetting.PWM_SECURITY_KEY );
761-
762-
if ( configValue == null || configValue.getStringValue().isEmpty() )
754+
if ( dataCache.pwmSecurityKey == null )
763755
{
764-
final String errorMsg = "Security Key value is not configured,will generate temp value for use by runtime instance";
765-
final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_INVALID_SECURITY_KEY, errorMsg );
766-
LOGGER.warn( errorInfo.toDebugStr() );
767-
if ( tempInstanceKey == null )
756+
final PasswordData configValue = readSettingAsPassword( PwmSetting.PWM_SECURITY_KEY );
757+
758+
if ( configValue == null || configValue.getStringValue().isEmpty() )
768759
{
769-
tempInstanceKey = new PwmSecurityKey( PwmRandom.getInstance().alphaNumericString( 256 ) );
760+
final String errorMsg = "Security Key value is not configured, will generate temp value for use by runtime instance";
761+
final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_INVALID_SECURITY_KEY, errorMsg );
762+
LOGGER.warn( errorInfo.toDebugStr() );
763+
if ( tempInstanceKey == null )
764+
{
765+
tempInstanceKey = new PwmSecurityKey( PwmRandom.getInstance().alphaNumericString( 1024 ) );
766+
}
767+
dataCache.pwmSecurityKey = tempInstanceKey;
770768
}
771-
return tempInstanceKey;
772-
}
769+
else
770+
{
771+
final int minSecurityKeyLength = Integer.parseInt( readAppProperty( AppProperty.SECURITY_CONFIG_MIN_SECURITY_KEY_LENGTH ) );
772+
if ( configValue.getStringValue().length() < minSecurityKeyLength )
773+
{
774+
final String errorMsg = "Security Key must be greater than 32 characters in length";
775+
final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_INVALID_SECURITY_KEY, errorMsg );
776+
throw new PwmUnrecoverableException( errorInfo );
777+
}
773778

774-
final int minSecurityKeyLength = Integer.parseInt( readAppProperty( AppProperty.SECURITY_CONFIG_MIN_SECURITY_KEY_LENGTH ) );
775-
if ( configValue.getStringValue().length() < minSecurityKeyLength )
776-
{
777-
final String errorMsg = "Security Key must be greater than 32 characters in length";
778-
final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_INVALID_SECURITY_KEY, errorMsg );
779-
throw new PwmUnrecoverableException( errorInfo );
779+
try
780+
{
781+
dataCache.pwmSecurityKey = new PwmSecurityKey( configValue.getStringValue() );
782+
}
783+
catch ( Exception e )
784+
{
785+
final String errorMsg = "unexpected error generating Security Key crypto: " + e.getMessage();
786+
final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_INVALID_SECURITY_KEY, errorMsg );
787+
LOGGER.error( errorInfo.toDebugStr(), e );
788+
throw new PwmUnrecoverableException( errorInfo );
789+
}
790+
}
780791
}
781792

782-
try
783-
{
784-
return new PwmSecurityKey( configValue.getStringValue() );
785-
}
786-
catch ( Exception e )
787-
{
788-
final String errorMsg = "unexpected error generating Security Key crypto: " + e.getMessage();
789-
final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_INVALID_SECURITY_KEY, errorMsg );
790-
LOGGER.error( errorInfo.toDebugStr(), e );
791-
throw new PwmUnrecoverableException( errorInfo );
792-
}
793+
return dataCache.pwmSecurityKey;
793794
}
794795

795796
public List<DataStorageMethod> getResponseStorageLocations( final PwmSetting setting )
@@ -1017,14 +1018,15 @@ private StoredValue readStoredValue( final PwmSetting setting )
10171018
return readValue;
10181019
}
10191020

1020-
private static class DataCache implements Serializable
1021+
private static class DataCache
10211022
{
10221023
private final Map<String, Map<Locale, PwmPasswordPolicy>> cachedPasswordPolicy = new LinkedHashMap<>();
10231024
private Map<Locale, String> localeFlagMap = null;
10241025
private final Map<PwmSetting, StoredValue> settings = new EnumMap<>( PwmSetting.class );
10251026
private final Map<String, Map<Locale, String>> customText = new LinkedHashMap<>();
10261027
private final Map<ProfileDefinition, Map> profileCache = new LinkedHashMap<>();
10271028
private Map<String, String> appPropertyOverrides = null;
1029+
private PwmSecurityKey pwmSecurityKey;
10281030
}
10291031

10301032
public Map<AppProperty, String> readAllNonDefaultAppProperties( )
@@ -1125,9 +1127,9 @@ private Profile newProfileForID( final ProfileDefinition profileDefinition, fina
11251127
return profileFactory.makeFromStoredConfiguration( storedConfiguration, profileID );
11261128
}
11271129

1128-
public StoredConfigurationImpl getStoredConfiguration( ) throws PwmUnrecoverableException
1130+
public StoredConfiguration getStoredConfiguration( ) throws PwmUnrecoverableException
11291131
{
1130-
final StoredConfigurationImpl copiedStoredConfiguration = StoredConfigurationImpl.copy( storedConfiguration );
1132+
final StoredConfiguration copiedStoredConfiguration = this.storedConfiguration.copy();
11311133
copiedStoredConfiguration.lock();
11321134
return copiedStoredConfiguration;
11331135
}
@@ -1149,10 +1151,13 @@ public String configurationHash( )
11491151

11501152
public Set<PwmSetting> nonDefaultSettings( )
11511153
{
1152-
final Set returnSet = new LinkedHashSet();
1153-
for ( final StoredConfigurationImpl.SettingValueRecord valueRecord : this.storedConfiguration.modifiedSettings() )
1154+
final Set<PwmSetting> returnSet = new LinkedHashSet<>();
1155+
for ( final StoredConfigItemKey key : this.storedConfiguration.modifiedSettings() )
11541156
{
1155-
returnSet.add( valueRecord.getSetting() );
1157+
if ( key.getRecordType() == StoredConfigItemKey.RecordType.SETTING )
1158+
{
1159+
returnSet.add( key.toPwmSetting() );
1160+
}
11561161
}
11571162
return returnSet;
11581163
}

server/src/main/java/password/pwm/config/PwmSetting.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
package password.pwm.config;
2222

23+
import password.pwm.config.stored.StoredConfigXmlConstants;
2324
import password.pwm.config.value.PasswordValue;
2425
import password.pwm.config.value.ValueFactory;
2526
import password.pwm.i18n.Config;
@@ -39,6 +40,7 @@
3940
import java.util.List;
4041
import java.util.Locale;
4142
import java.util.Map;
43+
import java.util.Optional;
4244
import java.util.Set;
4345
import java.util.function.Supplier;
4446
import java.util.regex.Pattern;
@@ -1376,20 +1378,17 @@ public Map<String, String> getOptions( )
13761378
{
13771379
final Map<String, String> returnList = new LinkedHashMap<>();
13781380
final XmlElement settingElement = PwmSettingXml.readSettingXml( this );
1379-
final XmlElement optionsElement = settingElement.getChild( "options" );
1380-
if ( optionsElement != null )
1381+
final Optional<XmlElement> optionsElement = settingElement.getChild( PwmSettingXml.XML_ELEMENT_OPTIONS );
1382+
if ( optionsElement.isPresent() )
13811383
{
1382-
final List<XmlElement> optionElements = optionsElement.getChildren( "option" );
1383-
if ( optionElements != null )
1384+
final List<XmlElement> optionElements = optionsElement.get().getChildren( PwmSettingXml.XML_ELEMENT_OPTION );
1385+
for ( final XmlElement optionElement : optionElements )
13841386
{
1385-
for ( final XmlElement optionElement : optionElements )
1387+
if ( optionElement.getAttributeValue( StoredConfigXmlConstants.XML_ELEMENT_VALUE ) == null )
13861388
{
1387-
if ( optionElement.getAttributeValue( "value" ) == null )
1388-
{
1389-
throw new IllegalStateException( "option element is missing 'value' attribute for key " + this.getKey() );
1390-
}
1391-
returnList.put( optionElement.getAttributeValue( "value" ), optionElement.getText() );
1389+
throw new IllegalStateException( "option element is missing 'value' attribute for key " + this.getKey() );
13921390
}
1391+
returnList.put( optionElement.getAttributeValue( StoredConfigXmlConstants.XML_ELEMENT_VALUE ), optionElement.getText() );
13931392
}
13941393
}
13951394
final Map<String, String> finalList = Collections.unmodifiableMap( returnList );
@@ -1405,10 +1404,10 @@ public Map<PwmSettingProperty, String> getProperties( )
14051404
{
14061405
final Map<PwmSettingProperty, String> newProps = new LinkedHashMap<>();
14071406
final XmlElement settingElement = PwmSettingXml.readSettingXml( this );
1408-
final XmlElement propertiesElement = settingElement.getChild( "properties" );
1409-
if ( propertiesElement != null )
1407+
final Optional<XmlElement> propertiesElement = settingElement.getChild( "properties" );
1408+
if ( propertiesElement.isPresent() )
14101409
{
1411-
final List<XmlElement> propertyElements = propertiesElement.getChildren( "property" );
1410+
final List<XmlElement> propertyElements = propertiesElement.get().getChildren( "property" );
14121411
if ( propertyElements != null )
14131412
{
14141413
for ( final XmlElement propertyElement : propertyElements )
@@ -1576,12 +1575,12 @@ public Pattern getRegExPattern( )
15761575
if ( pattern == null )
15771576
{
15781577
final XmlElement settingNode = PwmSettingXml.readSettingXml( this );
1579-
final XmlElement regexNode = settingNode.getChild( "regex" );
1580-
if ( regexNode != null )
1578+
final Optional<XmlElement> regexNode = settingNode.getChild( "regex" );
1579+
if ( regexNode.isPresent() )
15811580
{
15821581
try
15831582
{
1584-
final Pattern output = Pattern.compile( regexNode.getText() );
1583+
final Pattern output = Pattern.compile( regexNode.get().getText() );
15851584
pattern = ( ) -> output;
15861585
}
15871586
catch ( PatternSyntaxException e )

server/src/main/java/password/pwm/config/PwmSettingCategory.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.List;
3333
import java.util.Locale;
3434
import java.util.Map;
35+
import java.util.Optional;
3536
import java.util.TreeMap;
3637
import java.util.function.Supplier;
3738

@@ -322,10 +323,10 @@ private password.pwm.config.PwmSetting readProfileSettingFromXml( final boolean
322323
while ( nextCategory != null )
323324
{
324325
final XmlElement categoryElement = PwmSettingXml.readCategoryXml( nextCategory );
325-
final XmlElement profileElement = categoryElement.getChild( "profile" );
326-
if ( profileElement != null )
326+
final Optional<XmlElement> profileElement = categoryElement.getChild( "profile" );
327+
if ( profileElement.isPresent() )
327328
{
328-
final String settingKey = profileElement.getAttributeValue( "setting" );
329+
final String settingKey = profileElement.get().getAttributeValue( "setting" );
329330
if ( settingKey != null )
330331
{
331332
return password.pwm.config.PwmSetting.forKey( settingKey );

server/src/main/java/password/pwm/config/PwmSettingFlag.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,5 @@ public enum PwmSettingFlag
5454

5555
WebService_NoBody,
5656

57+
Deprecated,
5758
}

server/src/main/java/password/pwm/config/PwmSettingProperty.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
public enum PwmSettingProperty
2424
{
25-
2625
ModificationWarning,
2726

2827
Minimum,
@@ -36,4 +35,6 @@ public enum PwmSettingProperty
3635
Cert_ImportHandler,
3736

3837
MethodType,
38+
39+
Restart_Requirements,
3940
}

server/src/main/java/password/pwm/config/PwmSettingSyntax.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public enum PwmSettingSyntax
8383
this.storedValueImpl = storedValueImpl;
8484
}
8585

86-
public StoredValue.StoredValueFactory getStoredValueImpl( )
86+
public StoredValue.StoredValueFactory getFactory( )
8787
{
8888
return storedValueImpl;
8989
}

0 commit comments

Comments
 (0)