private void GetConfigDefinitionUpdates(
bool requireUpdates, ConfigurationSaveMode saveMode, bool forceSaveAll,
out ConfigDefinitionUpdates definitionUpdates, out ArrayList configSourceUpdates) {
definitionUpdates = new ConfigDefinitionUpdates();
configSourceUpdates = null;
bool hasChanged = HasRemovedSections;
// Loop through all the section records.
if (_sectionRecords != null) {
InitProtectedConfigurationSection(); // Make sure we have the initialized the protected config section, otherwise the foreach loop may blow up
foreach (DictionaryEntry de in _sectionRecords) {
string configKey = (string)de.Key;
SectionRecord sectionRecord = (SectionRecord) de.Value;
sectionRecord.AddUpdate = false;
bool addUpdate = sectionRecord.HasFileInput; // If true, add this section to definitionUpdates, and optinally to configSourceUpdates
bool allowOverride = true;
bool inheritInChildApplications = true;
bool moved = false;
string updatedXml = null;
bool addToConfigSourceUpdates = false; // If true, we have to update the external config file for this section
if (!sectionRecord.HasResult) {
if (sectionRecord.HasFileInput) {
SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
allowOverride = !sectionXmlInfo.LockChildren;
inheritInChildApplications = !sectionXmlInfo.SkipInChildApps;
addToConfigSourceUpdates = requireUpdates && !String.IsNullOrEmpty(sectionXmlInfo.ConfigSource);
}
}
else {
ConfigurationSection configSection = (ConfigurationSection) sectionRecord.Result;
allowOverride = configSection.SectionInformation.AllowOverride;
inheritInChildApplications = configSection.SectionInformation.InheritInChildApplications;
// it is an error to require a location section when the type doesn't allow locations.
if (!configSection.SectionInformation.AllowLocation && (!allowOverride || !inheritInChildApplications)) {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_inconsistent_location_attributes, configKey));
}
addToConfigSourceUpdates = requireUpdates && !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource);
try {
bool isModified = configSection.SectionInformation.ForceSave ||
configSection.IsModified() ||
(forceSaveAll && !configSection.SectionInformation.IsLocked);
bool sectionAttributesModified = AreSectionAttributesModified(sectionRecord, configSection);
bool sectionContentModified = (isModified || configSection.SectionInformation.RawXml != null);
// Get the updated XML if the section has been modified.
if (sectionContentModified || sectionAttributesModified) {
configSection.SectionInformation.VerifyIsEditable();
configSection.SectionInformation.Removed = false;
addUpdate = true;
moved = IsConfigSectionMoved(sectionRecord, configSection);
if (!addToConfigSourceUpdates) {
addToConfigSourceUpdates =
!String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource)
&& (sectionContentModified || configSection.SectionInformation.ConfigSourceModified);
}
if ( isModified ||
configSection.SectionInformation.RawXml == null ||
saveMode == ConfigurationSaveMode.Full) {
// Note: we won't use RawXml if saveMode == Full because Full means we want to
// write all properties, and RawXml may not have all properties.
ConfigurationSection parentConfigSection = FindImmediateParentSection(configSection);
updatedXml = configSection.SerializeSection(parentConfigSection, configSection.SectionInformation.Name, saveMode);
ValidateSectionXml(updatedXml, configKey);
}
else {
updatedXml = configSection.SectionInformation.RawXml;
}
if (string.IsNullOrEmpty(updatedXml)) {
//
// We always need to emit a section, even if empty, when:
// * The section has configSoure
// * The section is in a location section that has non-default attributes
// * The section is encrypted.
//
if ( !String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource) ||
!configSection.SectionInformation.LocationAttributesAreDefault ||
(configSection.SectionInformation.ProtectionProvider != null)) {
updatedXml = WriteEmptyElement(configSection.SectionInformation.Name);
}
}
if (string.IsNullOrEmpty(updatedXml)) {
configSection.SectionInformation.Removed = true;
// configSection.ElementPresent = false;
updatedXml = null;
addUpdate = false;
if (sectionRecord.HasFileInput) {
hasChanged = true;
}
}
else {
// configSection.ElementPresent = true;
if (sectionAttributesModified || moved || String.IsNullOrEmpty(configSection.SectionInformation.ConfigSource)) {
hasChanged = true;
}
// Encrypt if required.
if (configSection.SectionInformation.ProtectionProvider != null) {
ProtectedConfigurationSection protectedConfig = GetSection(BaseConfigurationRecord.RESERVED_SECTION_PROTECTED_CONFIGURATION) as ProtectedConfigurationSection;
try {
string encryptedSection = Host.EncryptSection(updatedXml, configSection.SectionInformation.ProtectionProvider, protectedConfig);
updatedXml = ProtectedConfigurationSection.FormatEncryptedSection(encryptedSection, configSection.SectionInformation.Name, configSection.SectionInformation.ProtectionProvider.Name);
}
catch (Exception e) {
throw new ConfigurationErrorsException(
SR.GetString(SR.Encryption_failed, configSection.SectionInformation.SectionName, configSection.SectionInformation.ProtectionProvider.Name, e.Message),
e);
}
catch {
throw new ConfigurationErrorsException(
SR.GetString(SR.Encryption_failed, configSection.SectionInformation.SectionName, configSection.SectionInformation.ProtectionProvider.Name, ExceptionUtil.NoExceptionInformation));
}
}
}
}
else if (configSection.SectionInformation.Removed) {
addUpdate = false;
if (sectionRecord.HasFileInput) {
hasChanged = true;
}
}
}
catch (Exception e) {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_exception_in_config_section_handler, configSection.SectionInformation.SectionName), e);
}
catch {
throw new ConfigurationErrorsException(SR.GetString(SR.Config_exception_in_config_section_handler, configSection.SectionInformation.SectionName));
}
}
if (addUpdate) {
VerifySectionUnlocked(sectionRecord.ConfigKey, null);
sectionRecord.AddUpdate = true;
DefinitionUpdate definitionUpdate = definitionUpdates.AddUpdate(allowOverride, inheritInChildApplications, moved, updatedXml, sectionRecord);
if (addToConfigSourceUpdates) {
if (configSourceUpdates == null) {
configSourceUpdates = new ArrayList();
}
configSourceUpdates.Add(definitionUpdate);
}
}
}
}
if (_flags[ ForceLocationWritten ]) {
// We must write the location tag
hasChanged = true;
definitionUpdates.RequireLocation = true;
}
if (_flags[ SuggestLocationRemoval ]) {
// We should try to remove location
hasChanged = true;
}
if (hasChanged) {
definitionUpdates.CompleteUpdates();
}
else {
definitionUpdates = null;
}
}