SessionStateItemCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / xsp / System / Web / State / SessionStateItemCollection.cs / 2 / SessionStateItemCollection.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * SessionStateItemCollection 
 *
 * Copyright (c) 1998-1999, Microsoft Corporation 
 *
 */

namespace System.Web.SessionState { 

    using System.IO; 
    using System.Collections; 
    using System.Collections.Specialized;
    using System.Web.Util; 
    using System.Security;
    using System.Security.Permissions;

    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    public interface ISessionStateItemCollection : ICollection { 
 
        Object this[String name]
        { 
            get;
            set;
        }
 
        Object this[int index]
        { 
            get; 
            set;
        } 

        void Remove(String name);

        void RemoveAt(int index); 

        void Clear(); 
 
        NameObjectCollectionBase.KeysCollection Keys {
            get; 
        }

        bool Dirty {
            get; 
            set;
        } 
    } 

    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
    public sealed class SessionStateItemCollection : NameObjectCollectionBase, ISessionStateItemCollection {

        class KeyedCollection : NameObjectCollectionBase {
 
            internal KeyedCollection(int count) : base(count, Misc.CaseInsensitiveInvariantKeyComparer) {
            } 
 
            internal Object this[String name]
            { 
                get {
                    return BaseGet(name);
                }
 
                set {
                    Object oldValue = BaseGet(name); 
                    if (oldValue == null && value == null) 
                        return;
 
                    BaseSet(name, value);
                }
            }
 
            internal Object this[int index]
            { 
                get { 
                    return BaseGet(index);
                } 

                set {
                    Object oldValue = BaseGet(index);
 
                    // We don't expect null value
                    Debug.Assert(value != null); 
 
                    BaseSet(index, value);
                } 
            }

            internal void Remove(String name) {
                BaseRemove(name); 
            }
 
            internal void RemoveAt(int index) { 
                BaseRemoveAt(index);
            } 

            internal void Clear() {
                BaseClear();
            } 

            internal string GetKey(  int index) { 
                return BaseGetKey(index); 
            }
 
            internal bool ContainsKey(string name) {
                // Please note that we don't expect null value to be inserted.
                return (BaseGet(name) != null);
            } 
        }
 
        static Hashtable s_immutableTypes; 
        const int       NO_NULL_KEY = -1;
        const int       SIZE_OF_INT32 = 4; 
        bool            _dirty;
        KeyedCollection _serializedItems;
        Stream          _stream;
        int             _iLastOffset; 
        object          _serializedItemsLock = new object();
 
        public SessionStateItemCollection() : base(Misc.CaseInsensitiveInvariantKeyComparer) { 
        }
 
        static SessionStateItemCollection() {
            Type t;
            s_immutableTypes = new Hashtable(19);
 
            t=typeof(String);
            s_immutableTypes.Add(t, t); 
            t=typeof(Int32); 
            s_immutableTypes.Add(t, t);
            t=typeof(Boolean); 
            s_immutableTypes.Add(t, t);
            t=typeof(DateTime);
            s_immutableTypes.Add(t, t);
            t=typeof(Decimal); 
            s_immutableTypes.Add(t, t);
            t=typeof(Byte); 
            s_immutableTypes.Add(t, t); 
            t=typeof(Char);
            s_immutableTypes.Add(t, t); 
            t=typeof(Single);
            s_immutableTypes.Add(t, t);
            t=typeof(Double);
            s_immutableTypes.Add(t, t); 
            t=typeof(SByte);
            s_immutableTypes.Add(t, t); 
            t=typeof(Int16); 
            s_immutableTypes.Add(t, t);
            t=typeof(Int64); 
            s_immutableTypes.Add(t, t);
            t=typeof(UInt16);
            s_immutableTypes.Add(t, t);
            t=typeof(UInt32); 
            s_immutableTypes.Add(t, t);
            t=typeof(UInt64); 
            s_immutableTypes.Add(t, t); 
            t=typeof(TimeSpan);
            s_immutableTypes.Add(t, t); 
            t=typeof(Guid);
            s_immutableTypes.Add(t, t);
            t=typeof(IntPtr);
            s_immutableTypes.Add(t, t); 
            t=typeof(UIntPtr);
            s_immutableTypes.Add(t, t); 
        } 

        static internal bool IsImmutable(Object o) { 
            return s_immutableTypes[o.GetType()] != null;
        }

        internal void DeserializeAllItems() { 
            if (_serializedItems == null) {
                return; 
            } 

            lock (_serializedItemsLock) { 
                for (int i = 0; i < _serializedItems.Count; i++) {
                    DeserializeItem(_serializedItems.GetKey(i), false);
                }
            } 
        }
 
        void DeserializeItem(int index) { 
            // No-op if SessionStateItemCollection is not deserialized from a persistent storage.
            if (_serializedItems == null) { 
                return;
            }

#if DBG 
            // The keys in _serializedItems should match the beginning part of
            // the list in NameObjectCollectionBase 
            for (int i=0; i < _serializedItems.Count; i++) { 
                Debug.Assert(_serializedItems.GetKey(i) == BaseGetKey(i));
            } 
#endif

            lock (_serializedItemsLock) {
                // No-op if the item isn't serialized. 
                if (index >= _serializedItems.Count) {
                    return; 
                } 

                DeserializeItem(_serializedItems.GetKey(index), false); 
            }
        }

        [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] 
        [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)]
        private object ReadValueFromStreamWithAssert() { 
            return AltSerialization.ReadValueFromStream(new BinaryReader(_stream)); 
        }
 
        void DeserializeItem(String name, bool check) {
            int             offset;
            object          val;
 
            lock (_serializedItemsLock) {
                if (check) { 
                    // No-op if SessionStateItemCollection is not deserialized from a persistent storage, 
                    if (_serializedItems == null) {
                        return; 
                    }

                    // User is asking for an item we don't have.
                    if (!_serializedItems.ContainsKey(name)) { 
                        return;
                    } 
                } 

                Debug.Assert(_serializedItems != null); 
                Debug.Assert(_stream != null);

                offset = (int)_serializedItems[name];
                if (offset < 0) { 
                    // It has been deserialized already.
                    return; 
                } 

                // Position the stream to the place where the item is stored. 
                _stream.Seek(offset, SeekOrigin.Begin);

                // Set the value
                Debug.Trace("SessionStateItemCollection", "Deserialized an item: keyname=" + name); 

                // VSWhidbey 427316: Sandbox Serialization in non full trust cases 
                if (HttpRuntime.NamedPermissionSet != null && HttpRuntime.ProcessRequestInApplicationTrust) { 
                    HttpRuntime.NamedPermissionSet.PermitOnly();
                } 

                // This deserialization work used to be done in AcquireRequestState event when
                // there is no user code on the stack.
                // In whidbey we added this on-demand deserialization for performance reason.  However, 
                // in medium and low trust cases the page doesn't have permission to do it.
                // So we have to assert the permission. 
                // (See VSWhidbey 275003) 
                val = ReadValueFromStreamWithAssert();
 
                BaseSet(name, val);

                // At the end, mark the item as deserialized by making it -ve.
                // If the offset is zero, we will use -ve Int32.MaxValue to mark it 
                // as deserialized.
                if (offset == 0) { 
                    _serializedItems[name] = Int32.MaxValue * -1; 
                }
                else if (offset > 0) { 
                    _serializedItems[name] = offset * -1;
                }
                else {
                    Debug.Fail("offset should never be zero within locked deserializeItem!"); 
                }
            } 
 
        }
 
        void MarkItemDeserialized(String name) {
            // No-op if SessionStateItemCollection is not deserialized from a persistent storage,
            if (_serializedItems == null) {
                return; 
            }
 
            lock (_serializedItemsLock) { 
                // If the serialized collection contains this key,
                // set it as deserialized by making it -ve. 
                if (_serializedItems.ContainsKey(name)) {
                    int offset = (int)_serializedItems[name];

                    // Mark the item as deserialized by making it -ve. 
                    // If the offset is zero, we will use -ve Int32.MaxValue to mark it
                    // as deserialized. 
 
                    if (offset == 0) {
                        _serializedItems[name] = Int32.MaxValue * -1; 
                    }
                    else if (offset > 0) {
                        _serializedItems[name] = offset * -1;
                    } 
                }
            } 
        } 

        void MarkItemDeserialized(int index) { 
            // No-op if SessionStateItemCollection is not deserialized from a persistent storage,
            if (_serializedItems == null) {
                return;
            } 

#if DBG 
            // The keys in _serializedItems should match the beginning part of 
            // the list in NameObjectCollectionBase
            for (int i=0; i < _serializedItems.Count; i++) { 
                Debug.Assert(_serializedItems.GetKey(i) == BaseGetKey(i));
            }
#endif
 
            // No-op if the item isn't serialized.
            if (index >= _serializedItems.Count) { 
                return; 
            }
 
            lock (_serializedItemsLock) {
                int offset = (int)_serializedItems[index];

                // Mark the item as deserialized by making it -ve. 
                // If the offset is zero, we will use -ve Int32.MaxValue to mark it
                // as deserialized. 
 
                if (offset == 0) {
                    _serializedItems[index] = Int32.MaxValue * -1; 
                }
                else if (offset > 0) {
                    _serializedItems[index] = offset * -1;
                } 
            }
        } 
 
        public bool Dirty {
            get {return _dirty;} 
            set {_dirty = value;}
        }

        public Object this[String name] 
        {
            get { 
                DeserializeItem(name, true); 

                Object obj = BaseGet(name); 
                if (obj != null) {
                    if (!IsImmutable(obj)) {
                        // If the item is immutable (e.g. an array), then the caller has the ability to change
                        // its content without calling our setter.  So we have to mark the collection 
                        // as dirty.
                        Debug.Trace("SessionStateItemCollection", "Setting _dirty to true in get"); 
                        _dirty = true; 
                    }
                } 

                return obj;
            }
 
            set {
                MarkItemDeserialized(name); 
                Debug.Trace("SessionStateItemCollection", "Setting _dirty to true in set"); 
                BaseSet(name, value);
                _dirty = true; 
            }
        }

        public Object this[int index] 
        {
            get { 
                DeserializeItem(index); 

                Object obj = BaseGet(index); 
                if (obj != null) {
                    if (!IsImmutable(obj)) {
                        Debug.Trace("SessionStateItemCollection", "Setting _dirty to true in get");
                        _dirty = true; 
                    }
                } 
 
                return obj;
            } 

            set {
                MarkItemDeserialized(index);
                Debug.Trace("SessionStateItemCollection", "Setting _dirty to true in set"); 
                BaseSet(index, value);
                _dirty = true; 
            } 
        }
 

        public void Remove(String name) {
            lock (_serializedItemsLock) {
                if (_serializedItems != null) { 
                    _serializedItems.Remove(name);
                } 
 
                BaseRemove(name);
                _dirty = true; 
            }
        }

        public void RemoveAt(int index) { 
            lock (_serializedItemsLock) {
                if (_serializedItems != null && index < _serializedItems.Count) { 
                    _serializedItems.RemoveAt(index); 
                }
 
                BaseRemoveAt(index);
                _dirty = true;
            }
        } 

        public void Clear() { 
            lock (_serializedItemsLock) { 
                if (_serializedItems != null) {
                    _serializedItems.Clear(); 
                }
                BaseClear();
                _dirty = true;
            } 
        }
 
        public override IEnumerator GetEnumerator() { 
            // Have to deserialize all items; otherwise the enumerator won't
            // work because we'll keep on changing the collection during 
            // individual item deserialization
            DeserializeAllItems();

            return base.GetEnumerator(); 
        }
 
        public override NameObjectCollectionBase.KeysCollection Keys { 
            get {
                // Unfortunately, we have to deserialize all items first, because 
                // Keys.GetEnumerator might be called and we have the same problem
                // as in GetEnumerator() above.
                DeserializeAllItems();
 
                return base.Keys;
            } 
        } 

        [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] 
        [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)]
        private void WriteValueToStreamWithAssert(object value, BinaryWriter writer) {
            AltSerialization.WriteValueToStream(value, writer);
        } 

        public void Serialize(BinaryWriter writer) { 
            int     count; 
            int     i;
            long    iOffsetStart; 
            long    iValueStart;
            string  key;
            object  value;
            long    curPos; 
            byte[]  buffer = null;
            Stream  baseStream = writer.BaseStream; 
 
            // VSWhidbey 427316: Sandbox Serialization in non full trust cases
            if (HttpRuntime.NamedPermissionSet != null && HttpRuntime.ProcessRequestInApplicationTrust) { 
                HttpRuntime.NamedPermissionSet.PermitOnly();
            }

            lock (_serializedItemsLock) { 
                count = Count;
                writer.Write(count); 
 
                if (count > 0) {
                    if (BaseGet(null) != null) { 
                        // We have a value with a null key.  Find its index.
                        for (i = 0; i < count; i++) {
                            key = BaseGetKey(i);
                            if (key == null) { 
                                writer.Write(i);
                                break; 
                            } 
                        }
 
                        Debug.Assert(i != count);
                    }
                    else {
                        writer.Write(NO_NULL_KEY); 
                    }
 
                    // Write out all the keys. 
                    for (i = 0; i < count; i++) {
                        key = BaseGetKey(i); 
                        if (key != null) {
                            writer.Write(key);
                        }
                    } 

                    // Next, allocate space to store the offset: 
                    // - We won't store the offset of first item because it's always zero. 
                    // - The offset of an item is counted from the beginning of serialized values
                    // - But we will store the offset of the first byte off the last item because 
                    //   we need that to calculate the size of the last item.
                    iOffsetStart = baseStream.Position;
                    baseStream.Seek(SIZE_OF_INT32 * count, SeekOrigin.Current);
 
                    iValueStart = baseStream.Position;
 
                    for (i = 0; i < count; i++) { 
                        // See if that item has not be deserialized yet.
                        if (_serializedItems != null && 
                            i < _serializedItems.Count &&
                            (int)_serializedItems[i] >= 0) {

                            int dataLength; 
                            int offset1, offset2;
 
                            Debug.Assert(_stream != null); 

                            // The item is read as serialized data from a store, and it's still 
                            // serialized, meaning no one has referenced it.  Just copy
                            // the bytes over.

                            // The length of the item is the difference between its offset 
                            // and next item offset, which are stored at position i and i+1 respectively,
                            // except for the last items. 
                            offset1 = (int)_serializedItems[i]; 

                            if (i == _serializedItems.Count - 1) { 
                                offset2 = _iLastOffset;
                            }
                            else {
                                offset2 = Math.Abs((int)_serializedItems[i + 1]); 
                            }
 
                            dataLength = offset2 - offset1; 

                            // Move the stream to the serialized data and copy it over to writer 
                            _stream.Seek(offset1, SeekOrigin.Begin);

                            if (buffer == null || buffer.Length < dataLength) {
                                buffer = new Byte[dataLength]; 
                            }
 
#if DBG 
                            int read =
#endif 
                            _stream.Read(buffer, 0, dataLength);
#if DBG
                            Debug.Assert(read == dataLength);
#endif 

                            baseStream.Write(buffer, 0, dataLength); 
                        } 
                        else {
                            value = BaseGet(i); 
                            WriteValueToStreamWithAssert(value, writer);
                        }

                        curPos = baseStream.Position; 

                        // Write the offset 
                        baseStream.Seek(i * SIZE_OF_INT32 + iOffsetStart, SeekOrigin.Begin); 
                        writer.Write((int)(curPos - iValueStart));
 
                        // Move back to current position
                        baseStream.Seek(curPos, SeekOrigin.Begin);

                        Debug.Trace("SessionStateItemCollection", 
                            "Serialize: curPost=" + curPos + ", offset= " + (int)(curPos - iValueStart));
                    } 
                } 
#if DBG
                writer.Write((byte)0xff); 
#endif
            }
        }
 
        public static SessionStateItemCollection Deserialize(BinaryReader reader) {
            SessionStateItemCollection   d = new SessionStateItemCollection(); 
            int                 count; 
            int                 nullKey;
            String              key; 
            int                 i;
            byte[]              buffer;

            count = reader.ReadInt32(); 

            if (count > 0) { 
                nullKey = reader.ReadInt32(); 

                d._serializedItems = new KeyedCollection(count); 

                // First, deserialize all the keys
                for (i = 0; i < count; i++) {
                    if (i == nullKey) { 
                        key = null;
                    } 
                    else { 
                        key = reader.ReadString();
                    } 

                    // Need to set them with null value first, so that
                    // the order of them items is correct.
                    d.BaseSet(key, null); 
                }
 
                // Next, deserialize all the offsets 
                for (i = 0; i < count; i++) {
                    if (i == 0) { 
                        d._serializedItems[d.BaseGetKey(i)] = 0;
                    }
                    else {
                        d._serializedItems[d.BaseGetKey(i)] = reader.ReadInt32(); 
                    }
                } 
 
                //
                d._iLastOffset = reader.ReadInt32(); 

                Debug.Trace("SessionStateItemCollection",
                    "Deserialize: _iLastOffset= " + d._iLastOffset);
 
                // _iLastOffset is the first byte past the last item, which equals
                // the total length of all serialized data 
                buffer = new byte[d._iLastOffset]; 
                int bytesRead = reader.BaseStream.Read(buffer, 0, d._iLastOffset);
                if (bytesRead != d._iLastOffset) { 
                    throw new HttpException(SR.GetString(SR.Invalid_session_state));
                }
                d._stream = new MemoryStream(buffer);
            } 

    #if DBG 
            Debug.Assert(reader.ReadByte() == 0xff); 
    #endif
 
            d._dirty = false;

            return d;
        } 
    }
}
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK