jrivard@gmail.com 6 jaren geleden
bovenliggende
commit
63934f0f46

+ 0 - 1
server/src/main/java/password/pwm/config/PwmSettingCategory.java

@@ -24,7 +24,6 @@ package password.pwm.config;
 
 import password.pwm.i18n.Config;
 import password.pwm.util.i18n.LocaleHelper;
-import password.pwm.util.LocaleHelper;
 import password.pwm.util.java.XmlElement;
 
 import java.util.ArrayList;

+ 77 - 119
server/src/main/java/password/pwm/config/stored/ConfigurationCleaner.java

@@ -22,23 +22,16 @@
 
 package password.pwm.config.stored;
 
-import org.jdom2.Comment;
-import org.jdom2.Document;
-import org.jdom2.Element;
-import org.jdom2.xpath.XPathExpression;
-import org.jdom2.xpath.XPathFactory;
 import password.pwm.PwmConstants;
 import password.pwm.bean.UserIdentity;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.StoredValue;
 import password.pwm.config.option.ADPolicyComplexity;
-import password.pwm.config.value.FormValue;
 import password.pwm.config.value.StringArrayValue;
 import password.pwm.config.value.StringValue;
-import password.pwm.config.value.UserPermissionValue;
-import password.pwm.config.value.data.FormConfiguration;
-import password.pwm.config.value.data.UserPermission;
 import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.util.java.XmlDocument;
+import password.pwm.util.java.XmlElement;
 import password.pwm.util.logging.PwmLogger;
 
 import java.util.ArrayList;
@@ -50,33 +43,53 @@ class ConfigurationCleaner
     private static final PwmLogger LOGGER = PwmLogger.forClass( ConfigurationCleaner.class );
     private static final String NEW_PROFILE_NAME = "default";
 
-    static void cleanup( final StoredConfigurationImpl configuration, final Document document )
+    private final StoredConfigurationImpl storedConfiguration;
+    private final XmlDocument document;
+
+    ConfigurationCleaner(
+            final StoredConfigurationImpl storedConfiguration, final XmlDocument document
+    )
+    {
+        this.storedConfiguration = storedConfiguration;
+        this.document = document;
+    }
+
+
+    static void cleanup(
+            final StoredConfigurationImpl storedConfiguration, final XmlDocument document
+    )
             throws PwmUnrecoverableException
     {
-        updateProperitiesWithoutType( configuration, document );
-        updateMandatoryElements( document );
-        profilizeNonProfiledSettings( configuration, document );
-        stripOrphanedProfileSettings( configuration, document );
-        migrateAppProperties( configuration, document );
-        updateDeprecatedSettings( configuration );
-        migrateDeprecatedProperties( configuration, document );
+        new ConfigurationCleaner( storedConfiguration, document ).cleanupImpl();
+    }
+
+    static void updateMandatoryElements(
+            final StoredConfigurationImpl storedConfiguration,
+            final XmlDocument document
+    )
+    {
+        new ConfigurationCleaner( storedConfiguration, document ).updateMandatoryElementsImpl();
     }
 
 
-    static void updateMandatoryElements( final Document document )
+    private void cleanupImpl(
+    )
+            throws PwmUnrecoverableException
     {
-        final Element rootElement = document.getRootElement();
+        updateProperitiesWithoutType( );
+        updateMandatoryElementsImpl();
+        profilizeNonProfiledSettings( );
+        stripOrphanedProfileSettings( );
+        migrateAppProperties( );
+        updateDeprecatedSettings( );
+        migrateDeprecatedProperties( );
+    }
 
-        {
-            final XPathExpression commentXPath = XPathFactory.instance().compile( "//comment()[1]" );
-            final Comment existingComment = ( Comment ) commentXPath.evaluateFirst( rootElement );
-            if ( existingComment != null )
-            {
-                existingComment.detach();
-            }
-            final Comment comment = new Comment( generateCommentText() );
-            rootElement.addContent( 0, comment );
-        }
+
+    private void updateMandatoryElementsImpl( )
+    {
+        final XmlElement rootElement = document.getRootElement();
+        rootElement.setComment( Collections.singletonList( generateCommentText() ) );
 
         rootElement.setAttribute( "pwmVersion", PwmConstants.BUILD_VERSION );
         rootElement.setAttribute( "pwmBuild", PwmConstants.BUILD_NUMBER );
@@ -86,20 +99,18 @@ class ConfigurationCleaner
         {
 
             // read correct (new) //properties[@type="config"]
-            final XPathExpression configPropertiesXpath = XPathFactory.instance().compile(
-                    "//" + StoredConfiguration.XML_ELEMENT_PROPERTIES + "[@" + StoredConfiguration.XML_ATTRIBUTE_TYPE + "=\""
-                            + StoredConfiguration.XML_ATTRIBUTE_VALUE_CONFIG + "\"]" );
-            final Element configPropertiesElement = ( Element ) configPropertiesXpath.evaluateFirst( rootElement );
+            final String configPropertiesXpath = "//" + StoredConfigurationImpl.XML_ELEMENT_PROPERTIES
+                    + "[@" + StoredConfigurationImpl.XML_ATTRIBUTE_TYPE + "=\"" + StoredConfigurationImpl.XML_ATTRIBUTE_VALUE_CONFIG + "\"]";
+            final XmlElement configPropertiesElement = document.evaluateXpathToElement( configPropertiesXpath );
 
             // read list of old //properties[not (@type)]/property
-            final XPathExpression nonAttributedProperty = XPathFactory.instance().compile(
-                    "//" + StoredConfiguration.XML_ELEMENT_PROPERTIES + "[not (@" + StoredConfiguration.XML_ATTRIBUTE_TYPE + ")]/"
-                            + StoredConfiguration.XML_ELEMENT_PROPERTY );
-            final List<Element> nonAttributedProperties = nonAttributedProperty.evaluate( rootElement );
+            final String nonAttributedPropertyXpath = "//" + StoredConfigurationImpl.XML_ELEMENT_PROPERTIES
+                    + "[not (@" + StoredConfigurationImpl.XML_ATTRIBUTE_TYPE + ")]/" + StoredConfigurationImpl.XML_ELEMENT_PROPERTY;
+            final List<XmlElement> nonAttributedProperties = document.evaluateXpathToElements( nonAttributedPropertyXpath );
 
             if ( configPropertiesElement != null && nonAttributedProperties != null )
             {
-                for ( final Element element : nonAttributedProperties )
+                for ( final XmlElement element : nonAttributedProperties )
                 {
                     element.detach();
                     configPropertiesElement.addContent( element );
@@ -107,12 +118,11 @@ class ConfigurationCleaner
             }
 
             // remove old //properties[not (@type] element
-            final XPathExpression oldPropertiesXpath = XPathFactory.instance().compile(
-                    "//" + StoredConfiguration.XML_ELEMENT_PROPERTIES + "[not (@" + StoredConfiguration.XML_ATTRIBUTE_TYPE + ")]" );
-            final List<Element> oldPropertiesElements = oldPropertiesXpath.evaluate( rootElement );
+            final String oldPropertiesXpath = "//" + StoredConfigurationImpl.XML_ELEMENT_PROPERTIES + "[not (@" + StoredConfigurationImpl.XML_ATTRIBUTE_TYPE + ")]";
+            final List<XmlElement> oldPropertiesElements = document.evaluateXpathToElements( oldPropertiesXpath );
             if ( oldPropertiesElements != null )
             {
-                for ( final Element element : oldPropertiesElements )
+                for ( final XmlElement element : oldPropertiesElements )
                 {
                     element.detach();
                 }
@@ -120,7 +130,7 @@ class ConfigurationCleaner
         }
     }
 
-    private static String generateCommentText( )
+    private String generateCommentText( )
     {
         final StringBuilder commentText = new StringBuilder();
         commentText.append( "\t\t" ).append( " " ).append( "\n" );
@@ -146,15 +156,15 @@ class ConfigurationCleaner
     }
 
 
-    private static void profilizeNonProfiledSettings( final StoredConfigurationImpl storedConfiguration, final Document document ) throws PwmUnrecoverableException
+    private void profilizeNonProfiledSettings()
+            throws PwmUnrecoverableException
     {
         for ( final PwmSetting setting : PwmSetting.values() )
         {
             if ( setting.getCategory().hasProfiles() )
             {
 
-                final XPathExpression xp = StoredConfigurationImpl.XPathBuilder.xpathForSetting( setting, null );
-                final Element settingElement = ( Element ) xp.evaluateFirst( document );
+                final XmlElement settingElement = storedConfiguration.getXmlHelper().xpathForSetting( setting, null );
                 if ( settingElement != null )
                 {
                     settingElement.detach();
@@ -177,8 +187,8 @@ class ConfigurationCleaner
                         profileStringDefinitions.add( NEW_PROFILE_NAME );
                     }
 
-                    final UserIdentity userIdentity = settingElement.getAttribute( StoredConfiguration.XML_ATTRIBUTE_MODIFY_USER ) != null
-                            ? UserIdentity.fromDelimitedKey( settingElement.getAttribute(  StoredConfiguration.XML_ATTRIBUTE_MODIFY_USER ).getValue() )
+                    final UserIdentity userIdentity = settingElement.getAttributeValue( StoredConfigurationImpl.XML_ATTRIBUTE_MODIFY_USER ) != null
+                            ? UserIdentity.fromDelimitedKey( settingElement.getAttributeValue(  StoredConfigurationImpl.XML_ATTRIBUTE_MODIFY_USER ) )
                             : null;
 
                     for ( final String destProfile : profileStringDefinitions )
@@ -193,17 +203,13 @@ class ConfigurationCleaner
         }
     }
 
-    private static void migrateDeprecatedProperties(
-            final StoredConfigurationImpl storedConfiguration,
-            final Document document
+    private void migrateDeprecatedProperties(
     )
             throws PwmUnrecoverableException
     {
-        final XPathFactory xpfac = XPathFactory.instance();
         {
             final String xpathString = "//property[@key=\"" + ConfigurationProperty.LDAP_TEMPLATE.getKey() + "\"]";
-            final XPathExpression xp = xpfac.compile( xpathString );
-            final List<Element> propertyElement = ( List<Element> ) xp.evaluate( document );
+            final List<XmlElement> propertyElement = document.evaluateXpathToElements( xpathString );
             if ( propertyElement != null && !propertyElement.isEmpty() )
             {
                 final String value = propertyElement.get( 0 ).getText();
@@ -213,8 +219,7 @@ class ConfigurationCleaner
         }
         {
             final String xpathString = "//property[@key=\"" + ConfigurationProperty.NOTES.getKey() + "\"]";
-            final XPathExpression xp = xpfac.compile( xpathString );
-            final List<Element> propertyElement = ( List<Element> ) xp.evaluate( document );
+            final List<XmlElement> propertyElement = document.evaluateXpathToElements( xpathString );
             if ( propertyElement != null && !propertyElement.isEmpty() )
             {
                 final String value = propertyElement.get( 0 ).getText();
@@ -224,32 +229,28 @@ class ConfigurationCleaner
         }
     }
 
-    private static void updateProperitiesWithoutType( final StoredConfigurationImpl storedConfiguration, final Document document )
+    private void updateProperitiesWithoutType()
     {
         final String xpathString = "//properties[not(@type)]";
-        final XPathFactory xpfac = XPathFactory.instance();
-        final XPathExpression xp = xpfac.compile( xpathString );
-        final List<Element> propertiesElements = ( List<Element> ) xp.evaluate( document );
-        for ( final Element propertiesElement : propertiesElements )
+        final List<XmlElement> propertiesElements = document.evaluateXpathToElements( xpathString );
+        for ( final XmlElement propertiesElement : propertiesElements )
         {
-            propertiesElement.setAttribute( StoredConfiguration.XML_ATTRIBUTE_TYPE, StoredConfiguration.XML_ATTRIBUTE_VALUE_CONFIG );
+            propertiesElement.setAttribute( StoredConfigurationImpl.XML_ATTRIBUTE_TYPE, StoredConfigurationImpl.XML_ATTRIBUTE_VALUE_CONFIG );
         }
     }
 
-    private static void stripOrphanedProfileSettings( final StoredConfigurationImpl storedConfiguration, final Document document )
+    private void stripOrphanedProfileSettings()
     {
-        final XPathFactory xpfac = XPathFactory.instance();
         for ( final PwmSetting setting : PwmSetting.values() )
         {
             if ( setting.getCategory().hasProfiles() )
             {
                 final List<String> validProfiles = storedConfiguration.profilesForSetting( setting );
                 final String xpathString = "//setting[@key=\"" + setting.getKey() + "\"]";
-                final XPathExpression xp = xpfac.compile( xpathString );
-                final List<Element> settingElements = ( List<Element> ) xp.evaluate( document );
-                for ( final Element settingElement : settingElements )
+                final List<XmlElement> settingElements =  document.evaluateXpathToElements( xpathString );
+                for ( final XmlElement settingElement : settingElements )
                 {
-                    final String profileID = settingElement.getAttributeValue( StoredConfiguration.XML_ATTRIBUTE_PROFILE );
+                    final String profileID = settingElement.getAttributeValue( StoredConfigurationImpl.XML_ATTRIBUTE_PROFILE );
                     if ( profileID != null )
                     {
                         if ( !validProfiles.contains( profileID ) )
@@ -263,14 +264,15 @@ class ConfigurationCleaner
         }
     }
 
-    private static void migrateAppProperties( final StoredConfigurationImpl storedConfiguration, final Document document ) throws PwmUnrecoverableException
+    private void migrateAppProperties(
+    )
+            throws PwmUnrecoverableException
     {
-        final XPathExpression xPathExpression = StoredConfigurationImpl.XPathBuilder.xpathForAppProperties();
-        final List<Element> appPropertiesElements = ( List<Element> ) xPathExpression.evaluate( document );
-        for ( final Element element : appPropertiesElements )
+        final List<XmlElement> appPropertiesElements = storedConfiguration.getXmlHelper().xpathForAppProperties();
+        for ( final XmlElement element : appPropertiesElements )
         {
-            final List<Element> properties = element.getChildren();
-            for ( final Element property : properties )
+            final List<XmlElement> properties = element.getChildren();
+            for ( final XmlElement property : properties )
             {
                 final String key = property.getAttributeValue( "key" );
                 final String value = property.getText();
@@ -292,7 +294,7 @@ class ConfigurationCleaner
         }
     }
 
-    private static void updateDeprecatedSettings( final StoredConfigurationImpl storedConfiguration ) throws PwmUnrecoverableException
+    private void updateDeprecatedSettings( ) throws PwmUnrecoverableException
     {
         final UserIdentity actor = new UserIdentity( "UpgradeProcessor", null );
         for ( final String profileID : storedConfiguration.profilesForSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY ) )
@@ -336,49 +338,5 @@ class ConfigurationCleaner
                 storedConfiguration.resetSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID, actor );
             }
         }
-
-        {
-            if ( !storedConfiguration.isDefaultValue( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES ) )
-            {
-                final List<String> oldValues = ( List<String> ) storedConfiguration.readSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES ).toNativeObject();
-
-                final List<FormConfiguration> newValues = new ArrayList<>();
-                for ( final String attribute : oldValues )
-                {
-                    final FormConfiguration formConfiguration = FormConfiguration.builder()
-                            .name( attribute )
-                            .labels( Collections.singletonMap( "", attribute ) )
-                            .build();
-                    newValues.add( formConfiguration );
-                }
-
-                final ValueMetaData existingData = storedConfiguration.readSettingMetadata( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES, null );
-                final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
-                        ? existingData.getUserIdentity()
-                        : actor;
-
-                storedConfiguration.writeSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_FORM, null, new FormValue( newValues ), newActor );
-                storedConfiguration.resetSetting( PwmSetting.PEOPLE_SEARCH_SEARCH_ATTRIBUTES, null, actor );
-            }
-        }
-
-        {
-            if ( !storedConfiguration.isDefaultValue( PwmSetting.REPORTING_SEARCH_FILTER ) )
-            {
-                final String oldValue = ( String ) storedConfiguration.readSetting( PwmSetting.REPORTING_SEARCH_FILTER ).toNativeObject();
-
-                final List<UserPermission> newValues = new ArrayList<>();
-                final UserPermission newPermission = new UserPermission( UserPermission.Type.ldapQuery, PwmConstants.PROFILE_ID_ALL, oldValue, null );
-                newValues.add( newPermission );
-
-                final ValueMetaData existingData = storedConfiguration.readSettingMetadata( PwmSetting.REPORTING_SEARCH_FILTER, null );
-                final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
-                        ? existingData.getUserIdentity()
-                        : actor;
-
-                storedConfiguration.writeSetting( PwmSetting.REPORTING_USER_MATCH, null, new UserPermissionValue( newValues ), newActor );
-                storedConfiguration.resetSetting( PwmSetting.REPORTING_SEARCH_FILTER, null, actor );
-            }
-        }
     }
 }

+ 1 - 1
server/src/main/java/password/pwm/config/stored/NGStoredConfigurationFactory.java

@@ -151,7 +151,7 @@ public class NGStoredConfigurationFactory
             }
             else
             {
-                LOGGER.trace( "parsing setting key=" + key + ", profile=" + storedConfigReference.getProfileID() );
+                LOGGER.trace( () -> "parsing setting key=" + key + ", profile=" + storedConfigReference.getProfileID() );
                 final XmlElement defaultElement = settingElement.getChild( StoredConfiguration.XML_ELEMENT_DEFAULT );
                 if ( defaultElement != null )
                 {

+ 12 - 278
server/src/main/java/password/pwm/config/stored/StoredConfigurationImpl.java

@@ -32,12 +32,10 @@ import password.pwm.config.PwmSettingSyntax;
 import password.pwm.config.PwmSettingTemplate;
 import password.pwm.config.PwmSettingTemplateSet;
 import password.pwm.config.StoredValue;
-import password.pwm.config.option.ADPolicyComplexity;
 import password.pwm.config.value.NamedSecretValue;
 import password.pwm.config.value.PasswordValue;
 import password.pwm.config.value.PrivateKeyValue;
 import password.pwm.config.value.StringArrayValue;
-import password.pwm.config.value.StringValue;
 import password.pwm.config.value.ValueFactory;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
@@ -106,7 +104,6 @@ public class StoredConfigurationImpl implements StoredConfiguration
     private final ReentrantReadWriteLock domModifyLock = new ReentrantReadWriteLock();
 
     private final XmlHelper xmlHelper = new XmlHelper();
-    private final ConfigurationCleaner configurationCleaner = new ConfigurationCleaner();
 
     public static StoredConfigurationImpl newStoredConfiguration( ) throws PwmUnrecoverableException
     {
@@ -217,7 +214,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
     {
         try
         {
-            configurationCleaner.cleanup();
+            ConfigurationCleaner.cleanup( this, document );
             final String createTime = JavaHelper.toIsoDate( Instant.now() );
             document.getRootElement().setAttribute( XML_ATTRIBUTE_CREATE_TIME, createTime );
         }
@@ -568,7 +565,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
     public void toXml( final OutputStream outputStream )
             throws IOException, PwmUnrecoverableException
     {
-        configurationCleaner.updateMandatoryElements( );
+        ConfigurationCleaner.updateMandatoryElements( this, document );
         XmlFactory.getFactory().outputDocument( document, outputStream );
     }
 
@@ -843,7 +840,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
 
         if ( theBundle.getString( keyName ) == null )
         {
-            LOGGER.info( "ignoring unknown key for bundle=" + bundleName + ", key=" + keyName );
+            LOGGER.info( () -> "ignoring unknown key for bundle=" + bundleName + ", key=" + keyName );
             return;
         }
 
@@ -851,7 +848,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
         resetLocaleBundleMap( bundleName, keyName );
         if ( localeMap == null || localeMap.isEmpty() )
         {
-            LOGGER.info( "cleared locale bundle map for bundle=" + bundleName + ", key=" + keyName );
+            LOGGER.info( () -> "cleared locale bundle map for bundle=" + bundleName + ", key=" + keyName );
             return;
         }
 
@@ -1028,7 +1025,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
 
 
         final String result = SecureEngine.hash( sb.toString(), PwmConstants.SETTING_CHECKSUM_HASH_METHOD );
-        LOGGER.trace( "computed setting checksum in " + TimeDuration.fromCurrent( startTime ).asCompactString() );
+        LOGGER.trace( () -> "computed setting checksum in " + TimeDuration.fromCurrent( startTime ).asCompactString() );
         return result;
     }
 
@@ -1076,7 +1073,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
         return passwordHash != null && passwordHash.length() > 0;
     }
 
-    private class XmlHelper
+    class XmlHelper
     {
         private XmlFactory getXmlFactory()
         {
@@ -1089,7 +1086,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
             return document.evaluateXpathToElement( xpathString );
         }
 
-        private XmlElement xpathForSetting( final PwmSetting setting, final String profileID )
+        XmlElement xpathForSetting( final PwmSetting setting, final String profileID )
         {
             final String xpathString;
             if ( profileID == null || profileID.length() < 1 )
@@ -1111,7 +1108,7 @@ public class StoredConfigurationImpl implements StoredConfiguration
             return document.evaluateXpathToElement( xpathString );
         }
 
-        private List<XmlElement> xpathForAppProperties( )
+        List<XmlElement> xpathForAppProperties( )
         {
             final String xpathString = "//" + XML_ELEMENT_PROPERTIES + "[@" + XML_ATTRIBUTE_TYPE + "=\"" + XML_ATTRIBUTE_VALUE_APP + "\"]";
             return document.evaluateXpathToElements( xpathString );
@@ -1132,273 +1129,6 @@ public class StoredConfigurationImpl implements StoredConfiguration
     }
 
 
-    private class ConfigurationCleaner
-    {
-        private void cleanup(
-        )
-                throws PwmUnrecoverableException
-        {
-            updateProperitiesWithoutType( );
-            updateMandatoryElements();
-            profilizeNonProfiledSettings( );
-            stripOrphanedProfileSettings( );
-            migrateAppProperties( );
-            updateDeprecatedSettings( );
-            migrateDeprecatedProperties( );
-        }
-
-
-        private void updateMandatoryElements( )
-        {
-            final XmlElement rootElement = document.getRootElement();
-            rootElement.setComment( Collections.singletonList( generateCommentText() ) );
-
-            rootElement.setAttribute( "pwmVersion", PwmConstants.BUILD_VERSION );
-            rootElement.setAttribute( "pwmBuild", PwmConstants.BUILD_NUMBER );
-            rootElement.setAttribute( "xmlVersion", XML_FORMAT_VERSION );
-
-            { // migrate old properties
-
-                // read correct (new) //properties[@type="config"]
-                final String configPropertiesXpath = "//" + XML_ELEMENT_PROPERTIES + "[@" + XML_ATTRIBUTE_TYPE + "=\"" + XML_ATTRIBUTE_VALUE_CONFIG + "\"]";
-                final XmlElement configPropertiesElement = document.evaluateXpathToElement( configPropertiesXpath );
-
-                // read list of old //properties[not (@type)]/property
-                final String nonAttributedPropertyXpath = "//" + XML_ELEMENT_PROPERTIES + "[not (@" + XML_ATTRIBUTE_TYPE + ")]/" + XML_ELEMENT_PROPERTY;
-                final List<XmlElement> nonAttributedProperties = document.evaluateXpathToElements( nonAttributedPropertyXpath );
-
-                if ( configPropertiesElement != null && nonAttributedProperties != null )
-                {
-                    for ( final XmlElement element : nonAttributedProperties )
-                    {
-                        element.detach();
-                        configPropertiesElement.addContent( element );
-                    }
-                }
-
-                // remove old //properties[not (@type] element
-                final String oldPropertiesXpath = "//" + XML_ELEMENT_PROPERTIES + "[not (@" + XML_ATTRIBUTE_TYPE + ")]";
-                final List<XmlElement> oldPropertiesElements = document.evaluateXpathToElements( oldPropertiesXpath );
-                if ( oldPropertiesElements != null )
-                {
-                    for ( final XmlElement element : oldPropertiesElements )
-                    {
-                        element.detach();
-                    }
-                }
-            }
-        }
-
-        private String generateCommentText( )
-        {
-            final StringBuilder commentText = new StringBuilder();
-            commentText.append( "\t\t" ).append( " " ).append( "\n" );
-            commentText.append( "\t\t" ).append( "This configuration file has been auto-generated by the " ).append( PwmConstants.PWM_APP_NAME ).append( " password self service application." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "WARNING: This configuration file contains sensitive security information, please handle with care!" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "WARNING: If a server is currently running using this configuration file, it will be restarted" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "         and the configuration updated immediately when it is modified." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "NOTICE: This file is encoded as UTF-8.  Do not save or edit this file with an editor that does not" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "        support UTF-8 encoding." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            commentText.append( "\t\t" ).append( "If unable to edit using the application ConfigurationEditor web UI, the following options are available." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "   or 1. Edit this file directly by hand." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "   or 2. Remove restrictions of the configuration by setting the property 'configIsEditable' to 'true' in this file.  This will " ).append( "\n" );
-            commentText.append( "\t\t" ).append( "         allow access to the ConfigurationEditor web UI without having to authenticate to an LDAP server first." ).append( "\n" );
-            commentText.append( "\t\t" ).append( "   or 3. Remove restrictions of the configuration by using the the command line utility. " ).append( "\n" );
-            commentText.append( "\t\t" ).append( "" ).append( "\n" );
-            return commentText.toString();
-        }
-
-
-        private void profilizeNonProfiledSettings()
-                throws PwmUnrecoverableException
-        {
-            final String NEW_PROFILE_NAME = "default";
-            for ( final PwmSetting setting : PwmSetting.values() )
-            {
-                if ( setting.getCategory().hasProfiles() )
-                {
-
-                    final XmlElement settingElement = xmlHelper.xpathForSetting( setting, null );
-                    if ( settingElement != null )
-                    {
-                        settingElement.detach();
-
-                        final PwmSetting profileSetting = setting.getCategory().getProfileSetting();
-                        final List<String> profileStringDefinitions = new ArrayList<>();
-                        {
-                            final StringArrayValue profileDefinitions = ( StringArrayValue ) readSetting( profileSetting );
-                            if ( profileDefinitions != null )
-                            {
-                                if ( profileDefinitions.toNativeObject() != null )
-                                {
-                                    profileStringDefinitions.addAll( profileDefinitions.toNativeObject() );
-                                }
-                            }
-                        }
-
-                        if (profileStringDefinitions.isEmpty()) {
-                            profileStringDefinitions.add( NEW_PROFILE_NAME );
-                        }
-
-                        final UserIdentity userIdentity = settingElement.getAttributeValue( XML_ATTRIBUTE_MODIFY_USER ) != null
-                                ? UserIdentity.fromDelimitedKey( settingElement.getAttributeValue(  XML_ATTRIBUTE_MODIFY_USER ) )
-                                : null;
-
-                        for ( final String destProfile : profileStringDefinitions )
-                        {
-                            LOGGER.info( "moving setting " + setting.getKey() + " without profile attribute to profile \"" + destProfile + "\"." );
-                            {
-                                writeSetting( profileSetting, new StringArrayValue( profileStringDefinitions ), userIdentity );
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        private void migrateDeprecatedProperties(
-        )
-                throws PwmUnrecoverableException
-        {
-            {
-                final String xpathString = "//property[@key=\"" + ConfigurationProperty.LDAP_TEMPLATE.getKey() + "\"]";
-                final List<XmlElement> propertyElement = document.evaluateXpathToElements( xpathString );
-                if ( propertyElement != null && !propertyElement.isEmpty() )
-                {
-                    final String value = propertyElement.get( 0 ).getText();
-                    writeSetting( PwmSetting.TEMPLATE_LDAP, new StringValue( value ), null );
-                    propertyElement.get( 0 ).detach();
-                }
-            }
-            {
-                final String xpathString = "//property[@key=\"" + ConfigurationProperty.NOTES.getKey() + "\"]";
-                final List<XmlElement> propertyElement = document.evaluateXpathToElements( xpathString );
-                if ( propertyElement != null && !propertyElement.isEmpty() )
-                {
-                    final String value = propertyElement.get( 0 ).getText();
-                    writeSetting( PwmSetting.NOTES, new StringValue( value ), null );
-                    propertyElement.get( 0 ).detach();
-                }
-            }
-        }
-
-        private void updateProperitiesWithoutType()
-        {
-            final String xpathString = "//properties[not(@type)]";
-            final List<XmlElement> propertiesElements = document.evaluateXpathToElements( xpathString );
-            for ( final XmlElement propertiesElement : propertiesElements )
-            {
-                propertiesElement.setAttribute( XML_ATTRIBUTE_TYPE, XML_ATTRIBUTE_VALUE_CONFIG );
-            }
-        }
-
-        private void stripOrphanedProfileSettings()
-        {
-            for ( final PwmSetting setting : PwmSetting.values() )
-            {
-                if ( setting.getCategory().hasProfiles() )
-                {
-                    final List<String> validProfiles = profilesForSetting( setting );
-                    final String xpathString = "//setting[@key=\"" + setting.getKey() + "\"]";
-                    final List<XmlElement> settingElements =  document.evaluateXpathToElements( xpathString );
-                    for ( final XmlElement settingElement : settingElements )
-                    {
-                        final String profileID = settingElement.getAttributeValue( XML_ATTRIBUTE_PROFILE );
-                        if ( profileID != null )
-                        {
-                            if ( !validProfiles.contains( profileID ) )
-                            {
-                                LOGGER.info( "removing setting " + setting.getKey() + " with profile \"" + profileID + "\", profile is not a valid profile" );
-                                settingElement.detach();
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        private void migrateAppProperties(
-        )
-                throws PwmUnrecoverableException
-        {
-            final List<XmlElement> appPropertiesElements = xmlHelper.xpathForAppProperties();
-            for ( final XmlElement element : appPropertiesElements )
-            {
-                final List<XmlElement> properties = element.getChildren();
-                for ( final XmlElement property : properties )
-                {
-                    final String key = property.getAttributeValue( "key" );
-                    final String value = property.getText();
-                    if ( key != null && !key.isEmpty() && value != null && !value.isEmpty() )
-                    {
-                        LOGGER.info( "migrating app-property config element '" + key + "' to setting " + PwmSetting.APP_PROPERTY_OVERRIDES.getKey() );
-                        final String newValue = key + "=" + value;
-                        List<String> existingValues = ( List<String> ) readSetting( PwmSetting.APP_PROPERTY_OVERRIDES ).toNativeObject();
-                        if ( existingValues == null )
-                        {
-                            existingValues = new ArrayList<>();
-                        }
-                        existingValues = new ArrayList<>( existingValues );
-                        existingValues.add( newValue );
-                        writeSetting( PwmSetting.APP_PROPERTY_OVERRIDES, new StringArrayValue( existingValues ), null );
-                    }
-                }
-                element.detach();
-            }
-        }
-
-        private void updateDeprecatedSettings( ) throws PwmUnrecoverableException
-        {
-            final UserIdentity actor = new UserIdentity( "UpgradeProcessor", null );
-            for ( final String profileID : profilesForSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY ) )
-            {
-                if ( !isDefaultValue( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID ) )
-                {
-                    final boolean ad2003Enabled = ( boolean ) readSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID ).toNativeObject();
-                    final StoredValue value;
-                    if ( ad2003Enabled )
-                    {
-                        value = new StringValue( ADPolicyComplexity.AD2003.toString() );
-                    }
-                    else
-                    {
-                        value = new StringValue( ADPolicyComplexity.NONE.toString() );
-                    }
-                    LOGGER.warn( "converting deprecated non-default setting " + PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY.getKey() + "/" + profileID
-                            + " to replacement setting " + PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY_LEVEL + ", value=" + value.toNativeObject().toString() );
-                    writeSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY_LEVEL, profileID, value, actor );
-                    resetSetting( PwmSetting.PASSWORD_POLICY_AD_COMPLEXITY, profileID, actor );
-                }
-            }
-
-            for ( final String profileID : profilesForSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME ) )
-            {
-                if ( !isDefaultValue( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID ) )
-                {
-                    final boolean enforceEnabled = ( boolean ) readSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID ).toNativeObject();
-                    final StoredValue value = enforceEnabled
-                            ? new StringValue( "NONE" )
-                            : new StringValue( "ALLOW" );
-                    final ValueMetaData existingData = readSettingMetadata( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID );
-                    LOGGER.warn( "converting deprecated non-default setting "
-                            + PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME.toMenuLocationDebug(profileID,PwmConstants.DEFAULT_LOCALE) + "/" + profileID
-                            + " to replacement setting " + PwmSetting.RECOVERY_MINIMUM_PASSWORD_LIFETIME_OPTIONS.toMenuLocationDebug( profileID, PwmConstants.DEFAULT_LOCALE )
-                            + ", value=" + value.toNativeObject().toString() );
-                    final UserIdentity newActor = existingData != null && existingData.getUserIdentity() != null
-                            ? existingData.getUserIdentity()
-                            : actor;
-                    writeSetting( PwmSetting.RECOVERY_MINIMUM_PASSWORD_LIFETIME_OPTIONS, profileID, value, newActor );
-                    resetSetting( PwmSetting.RECOVERY_ENFORCE_MINIMUM_PASSWORD_LIFETIME, profileID, actor );
-                }
-            }
-        }
-    }
-
-
     public static class ConfigRecordID implements Serializable, Comparable
     {
         private RecordType recordType;
@@ -1842,4 +1572,8 @@ public class StoredConfigurationImpl implements StoredConfiguration
         return new ArrayList<>( loopResults );
     }
 
+    XmlHelper getXmlHelper()
+    {
+        return xmlHelper;
+    }
 }