Exemplo n.º 1
0
        internal StreamInfo Clone() {
            StreamInfo clone = new StreamInfo();

            clone._sectionName  = this._sectionName;
            clone._configSource = this._configSource;
            clone._streamName   = this._streamName;
            clone._isMonitored  = this._isMonitored;
            clone._version      = this._version;

            return clone;
        }
        //
        // Set the configSource attribute on a ConfigurationSection
        //
        internal void ChangeConfigSource(
                SectionInformation sectionInformation,
                string oldConfigSource,
                string oldConfigSourceStreamName,
                string newConfigSource) {

            if (String.IsNullOrEmpty(oldConfigSource)) {
                oldConfigSource = null;
            }

            if (String.IsNullOrEmpty(newConfigSource)) {
                newConfigSource = null;
            }

            // Check if there is a change to config source
            if (StringUtil.EqualsIgnoreCase(oldConfigSource, newConfigSource))
                return;

            if (String.IsNullOrEmpty(ConfigStreamInfo.StreamName)) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_source_requires_file));
            }

            string newConfigSourceStreamName = null;
            if (newConfigSource != null) {
                newConfigSourceStreamName = Host.GetStreamNameForConfigSource(ConfigStreamInfo.StreamName, newConfigSource);
            }

            // Add the stream to the updates
            if (newConfigSourceStreamName != null) {
                //
                // Ensure that no parent is using the same config source stream
                //
                ValidateUniqueChildConfigSource(sectionInformation.ConfigKey, newConfigSourceStreamName, newConfigSource, null);

                StreamInfo streamInfo = (StreamInfo) _streamInfoUpdates[newConfigSourceStreamName];
                if (streamInfo != null) {
                    //
                    // Detect if another section in this file is using the same configSource
                    // with has a different section name.
                    //
                    if (streamInfo.SectionName != sectionInformation.ConfigKey) {
                        throw new ConfigurationErrorsException(
                            SR.GetString(SR.Config_source_cannot_be_shared, newConfigSource));
                    }
                }
                else {
                    //
                    // Add stream to updates
                    //
                    streamInfo = new StreamInfo(sectionInformation.ConfigKey, newConfigSource, newConfigSourceStreamName);
                    _streamInfoUpdates.Add(newConfigSourceStreamName, streamInfo);
                }
            }

            // remove old streamname if no longer referenced
            if (oldConfigSourceStreamName != null && !IsStreamUsed(oldConfigSourceStreamName)) {
                _streamInfoUpdates.Remove(oldConfigSourceStreamName);
            }

            // update the configSourceStreamName
            sectionInformation.ConfigSourceStreamName = newConfigSourceStreamName;
        }
        //
        // Update the config file with the changes in each ConfigurationSection
        //
        internal void SaveAs(string filename, ConfigurationSaveMode saveMode, bool forceUpdateAll) {

            // Get the updates.
            SectionUpdates declarationUpdates = GetConfigDeclarationUpdates(saveMode, forceUpdateAll);

            ConfigDefinitionUpdates definitionUpdates;
            ArrayList configSourceUpdates;
            bool checkedConfigForUpdates = false;
            bool requireUpdates = (filename != null);
            GetConfigDefinitionUpdates(requireUpdates, saveMode, forceUpdateAll, out definitionUpdates, out configSourceUpdates);

            if (filename != null) {
                Debug.Assert(filename.Length > 0, "The caller should make sure that filename is not empty");

                //
                // Verify that the filename is not being used.
                //
                // Note that if we are using a remote host, all the streamName's in _streamInfoUpdates
                // are actually fullpaths on the remote machine.  In this case there is no way to
                // detect if we have a conflict or not.
                if (!Host.IsRemote && _streamInfoUpdates.Contains(filename)) {
                    throw new ArgumentException(SR.GetString(SR.Filename_in_SaveAs_is_used_already, filename));
                }

                //
                // If there was no config file for this config record,
                // record the new stream name and version.
                //
                if (String.IsNullOrEmpty(ConfigStreamInfo.StreamName)) {
                    StreamInfo streamInfo = new StreamInfo(null, null, filename);
                    _streamInfoUpdates.Add(filename, streamInfo);

                    ConfigStreamInfo.StreamName = filename;
                    ConfigStreamInfo.StreamVersion = MonitorStream(null, null, ConfigStreamInfo.StreamName);
                }

                //
                // Update the host to redirect filenames
                //
                UpdateConfigHost.AddStreamname(ConfigStreamInfo.StreamName, filename, Host.IsRemote);

                // Redirect also all configSource filenames
                foreach (StreamInfo streamInfo in _streamInfoUpdates.Values) {
                    if (!String.IsNullOrEmpty(streamInfo.SectionName)) {
                        // Get the new configSource streamName based on the new filename path
                        string newStreamName = InternalConfigHost.StaticGetStreamNameForConfigSource(
                            filename, streamInfo.ConfigSource);

                    // Ask UpdateConfigHost to intercept them.
                    UpdateConfigHost.AddStreamname(streamInfo.StreamName, newStreamName, Host.IsRemote);
                    }
                }

            }

            if (!requireUpdates) {
                // Check if there are any updates needed for the
                // configuration record itself.
                requireUpdates = RecordItselfRequiresUpdates;
            }

            if (declarationUpdates != null || definitionUpdates != null || requireUpdates) {
                // Copy the input stream before opening the output stream.
                byte[] readBuffer = null;
                Encoding encoding = null;
                if (ConfigStreamInfo.HasStream) {
                    using (Stream streamRead = Host.OpenStreamForRead(ConfigStreamInfo.StreamName)) {
                        if (streamRead == null) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_file_has_changed), ConfigStreamInfo.StreamName, 0);
                        }

                        readBuffer = new byte[streamRead.Length];
                        int count = streamRead.Read(readBuffer, 0, (int) streamRead.Length);
                        if (count != streamRead.Length) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_data_read_count_mismatch));
                        }
                    }
                    // Read the first byte so that we can determine the encoding.
                    try {
                        using (StreamReader reader = new StreamReader(ConfigStreamInfo.StreamName)) {
                            if (reader.Peek() >= 0) {
                                reader.Read();
                            }

                            // Dev10 bug 687017 - Handle only UTF-16 explicitly, so that handling of other 
                            // encodings are not affected.
                            if (reader.CurrentEncoding is UnicodeEncoding) {
                                encoding = reader.CurrentEncoding;
                            }
                        }
                    }
                    catch {
                        // Ignore any errors, encoding will remain null.
                    }
                }

                string changedStreamName = FindChangedConfigurationStream();
                if (changedStreamName != null) {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_file_has_changed), changedStreamName, 0);
                }

                checkedConfigForUpdates = true;

                // Write the changes to the output stream.
                object writeContext = null;
                bool streamOpened = false;
                try {
                    try {
                        using (Stream streamWrite = Host.OpenStreamForWrite(ConfigStreamInfo.StreamName, null, ref writeContext)) {
                            streamOpened = true;
                            // Use the default StreamWriter constructor if encoding is null,
                            // otherwise specify the encoding.
                            using (StreamWriter streamWriter = encoding == null ? new StreamWriter(streamWrite) : new StreamWriter(streamWrite, encoding)) {
                                XmlUtilWriter utilWriter = new XmlUtilWriter(streamWriter, true);
                                if (ConfigStreamInfo.HasStream) {
                                    CopyConfig(declarationUpdates, definitionUpdates, readBuffer,
                                            ConfigStreamInfo.StreamName, NamespaceChangeNeeded, utilWriter);
                                }
                                else {
                                    CreateNewConfig(declarationUpdates, definitionUpdates, NamespaceChangeNeeded, utilWriter);
                                }
                            }
                        }
                    }
                    catch {
                        if (streamOpened) {
                            Host.WriteCompleted(ConfigStreamInfo.StreamName, false, writeContext);
                        }

                        throw;
                    }
                }
                //
                // Guarantee that exceptions contain at least the name of the stream by wrapping them
                // in a ConfigurationException.
                //
                catch (Exception e) {
                    throw ExceptionUtil.WrapAsConfigException(SR.GetString(SR.Config_error_loading_XML_file), e, ConfigStreamInfo.StreamName, 0);
                }

                Host.WriteCompleted(ConfigStreamInfo.StreamName, true, writeContext);

                // Update stream information for the config file
                ConfigStreamInfo.HasStream = true;
                ConfigStreamInfo.ClearStreamInfos();
                ConfigStreamInfo.StreamVersion = MonitorStream(null, null, ConfigStreamInfo.StreamName);
            }

            if (configSourceUpdates != null) {
                // If we haven't checked before, check now
                if (!checkedConfigForUpdates) {
                    string changedStreamName = FindChangedConfigurationStream();
                    if (changedStreamName != null) {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_file_has_changed), changedStreamName, 0);
                    }
                }

                // write updates
                foreach (DefinitionUpdate update in configSourceUpdates) {
                    SaveConfigSource(update);
                }
            }

            // Update state to reflect the changes to the config file
            UpdateRecords();
        }
        protected object MonitorStream(string configKey, string configSource, string streamname) {
            lock (this) {
                if (_flags[Closed]) {
                    return null;
                }

                StreamInfo streamInfo = (StreamInfo) ConfigStreamInfo.StreamInfos[streamname];
                if (streamInfo != null) {
                    if (streamInfo.SectionName != configKey) {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_source_cannot_be_shared, streamname));
                    }

                    if (streamInfo.IsMonitored) {
                        return streamInfo.Version;
                    }
                }
                else {
                    streamInfo = new StreamInfo(configKey, configSource, streamname);
                    ConfigStreamInfo.StreamInfos.Add(streamname, streamInfo);
                }
            }

            //
            // Call the host outside the lock to avoid deadlock.
            //
            object version = Host.GetStreamVersion(streamname);

            StreamChangeCallback callbackDelegate = null;

            lock (this) {
                if (_flags[Closed]) {
                    return null;
                }

                StreamInfo streamInfo = (StreamInfo) ConfigStreamInfo.StreamInfos[streamname];
                if (streamInfo.IsMonitored) {
                    return streamInfo.Version;
                }

                streamInfo.IsMonitored = true;
                streamInfo.Version = version;

                if (_flags[SupportsChangeNotifications]) {
                    if (ConfigStreamInfo.CallbackDelegate == null) {
                        ConfigStreamInfo.CallbackDelegate = new StreamChangeCallback(this.OnStreamChanged);
                    }

                    callbackDelegate = ConfigStreamInfo.CallbackDelegate;
                }
            }

            if (_flags[SupportsChangeNotifications]) {
                Host.StartMonitoringStreamForChanges(streamname, callbackDelegate);
            }

            return version;
        }
 internal void ChangeConfigSource(SectionInformation sectionInformation, string oldConfigSource, string oldConfigSourceStreamName, string newConfigSource)
 {
     if (string.IsNullOrEmpty(oldConfigSource))
     {
         oldConfigSource = null;
     }
     if (string.IsNullOrEmpty(newConfigSource))
     {
         newConfigSource = null;
     }
     if (!StringUtil.EqualsIgnoreCase(oldConfigSource, newConfigSource))
     {
         if (string.IsNullOrEmpty(base.ConfigStreamInfo.StreamName))
         {
             throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_source_requires_file"));
         }
         string configSourceStreamName = null;
         if (newConfigSource != null)
         {
             configSourceStreamName = base.Host.GetStreamNameForConfigSource(base.ConfigStreamInfo.StreamName, newConfigSource);
         }
         if (configSourceStreamName != null)
         {
             base.ValidateUniqueChildConfigSource(sectionInformation.ConfigKey, configSourceStreamName, newConfigSource, null);
             StreamInfo info = (StreamInfo) this._streamInfoUpdates[configSourceStreamName];
             if (info != null)
             {
                 if (info.SectionName != sectionInformation.ConfigKey)
                 {
                     throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_source_cannot_be_shared", new object[] { newConfigSource }));
                 }
             }
             else
             {
                 info = new StreamInfo(sectionInformation.ConfigKey, newConfigSource, configSourceStreamName);
                 this._streamInfoUpdates.Add(configSourceStreamName, info);
             }
         }
         if ((oldConfigSourceStreamName != null) && !this.IsStreamUsed(oldConfigSourceStreamName))
         {
             this._streamInfoUpdates.Remove(oldConfigSourceStreamName);
         }
         sectionInformation.ConfigSourceStreamName = configSourceStreamName;
     }
 }
 internal void SaveAs(string filename, ConfigurationSaveMode saveMode, bool forceUpdateAll)
 {
     ConfigDefinitionUpdates updates2;
     ArrayList list;
     SectionUpdates configDeclarationUpdates = this.GetConfigDeclarationUpdates(saveMode, forceUpdateAll);
     bool flag = false;
     bool requireUpdates = filename != null;
     this.GetConfigDefinitionUpdates(requireUpdates, saveMode, forceUpdateAll, out updates2, out list);
     if (filename != null)
     {
         if (!base.Host.IsRemote && this._streamInfoUpdates.Contains(filename))
         {
             throw new ArgumentException(System.Configuration.SR.GetString("Filename_in_SaveAs_is_used_already", new object[] { filename }));
         }
         if (string.IsNullOrEmpty(base.ConfigStreamInfo.StreamName))
         {
             StreamInfo info = new StreamInfo(null, null, filename);
             this._streamInfoUpdates.Add(filename, info);
             base.ConfigStreamInfo.StreamName = filename;
             base.ConfigStreamInfo.StreamVersion = base.MonitorStream(null, null, base.ConfigStreamInfo.StreamName);
         }
         this.UpdateConfigHost.AddStreamname(base.ConfigStreamInfo.StreamName, filename, base.Host.IsRemote);
         foreach (StreamInfo info2 in this._streamInfoUpdates.Values)
         {
             if (!string.IsNullOrEmpty(info2.SectionName))
             {
                 string newStreamname = InternalConfigHost.StaticGetStreamNameForConfigSource(filename, info2.ConfigSource);
                 this.UpdateConfigHost.AddStreamname(info2.StreamName, newStreamname, base.Host.IsRemote);
             }
         }
     }
     if (!requireUpdates)
     {
         requireUpdates = this.RecordItselfRequiresUpdates;
     }
     if (((configDeclarationUpdates != null) || (updates2 != null)) || requireUpdates)
     {
         byte[] buffer = null;
         Encoding currentEncoding = null;
         if (base.ConfigStreamInfo.HasStream)
         {
             using (Stream stream = base.Host.OpenStreamForRead(base.ConfigStreamInfo.StreamName))
             {
                 if (stream == null)
                 {
                     throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_file_has_changed"), base.ConfigStreamInfo.StreamName, 0);
                 }
                 buffer = new byte[stream.Length];
                 if (stream.Read(buffer, 0, (int) stream.Length) != stream.Length)
                 {
                     throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_data_read_count_mismatch"));
                 }
             }
             try
             {
                 using (StreamReader reader = new StreamReader(base.ConfigStreamInfo.StreamName))
                 {
                     if (reader.Peek() >= 0)
                     {
                         reader.Read();
                     }
                     if (reader.CurrentEncoding is UnicodeEncoding)
                     {
                         currentEncoding = reader.CurrentEncoding;
                     }
                 }
             }
             catch
             {
             }
         }
         string str2 = base.FindChangedConfigurationStream();
         if (str2 != null)
         {
             throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_file_has_changed"), str2, 0);
         }
         flag = true;
         object writeContext = null;
         bool flag3 = false;
         try
         {
             try
             {
                 using (Stream stream2 = base.Host.OpenStreamForWrite(base.ConfigStreamInfo.StreamName, null, ref writeContext))
                 {
                     flag3 = true;
                     using (StreamWriter writer = (currentEncoding == null) ? new StreamWriter(stream2) : new StreamWriter(stream2, currentEncoding))
                     {
                         XmlUtilWriter utilWriter = new XmlUtilWriter(writer, true);
                         if (base.ConfigStreamInfo.HasStream)
                         {
                             this.CopyConfig(configDeclarationUpdates, updates2, buffer, base.ConfigStreamInfo.StreamName, this.NamespaceChangeNeeded, utilWriter);
                         }
                         else
                         {
                             this.CreateNewConfig(configDeclarationUpdates, updates2, this.NamespaceChangeNeeded, utilWriter);
                         }
                     }
                 }
             }
             catch
             {
                 if (flag3)
                 {
                     base.Host.WriteCompleted(base.ConfigStreamInfo.StreamName, false, writeContext);
                 }
                 throw;
             }
         }
         catch (Exception exception)
         {
             throw ExceptionUtil.WrapAsConfigException(System.Configuration.SR.GetString("Config_error_loading_XML_file"), exception, base.ConfigStreamInfo.StreamName, 0);
         }
         base.Host.WriteCompleted(base.ConfigStreamInfo.StreamName, true, writeContext);
         base.ConfigStreamInfo.HasStream = true;
         base.ConfigStreamInfo.ClearStreamInfos();
         base.ConfigStreamInfo.StreamVersion = base.MonitorStream(null, null, base.ConfigStreamInfo.StreamName);
     }
     if (list != null)
     {
         if (!flag)
         {
             string str3 = base.FindChangedConfigurationStream();
             if (str3 != null)
             {
                 throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_file_has_changed"), str3, 0);
             }
         }
         foreach (DefinitionUpdate update in list)
         {
             this.SaveConfigSource(update);
         }
     }
     this.UpdateRecords();
 }