示例#1
0
            public _CacheEntry(string path, DateTime lastWriteAtLoad, IContactProperties properties)
            {
                Assert.IsFalse(string.IsNullOrEmpty(path));
                Assert.IsNotNull(properties);

                FilePath = path;
                LastModified = lastWriteAtLoad;
                Properties = properties;

                _timeToLive = _CachePolicy.TimeToLiveCount;
                // _weakProperties = null;
            }
示例#2
0
            public bool TryGetProperties(out IContactProperties properties)
            {
                properties = null;

                // File.GetLastWriteTime is documented as throwing UnauthorizedAccessException
                // when the file is missing.
                DateTime fileLastAccess;
                try
                {
                    fileLastAccess = File.GetLastWriteTimeUtc(FilePath);
                }
                // UnauthorizedAccessException is thrown in the case of a missing file.
                catch (UnauthorizedAccessException)
                {
                    // Can't get properties from a missing file.
                    return false;
                }
                //catch (FileNotFoundException) { exceptionRaised = true; }
                //catch (DirectoryNotFoundException) { exceptionRaised = true; }
                catch (Exception e)
                {
                    Assert.Fail("This path shouldn't have gotten into the dictionary.\n " + e.Message);
                    throw;
                }

                // Can use this only if the file hasn't been modified since it was added.
                if (!fileLastAccess.Equals(LastModified))
                {
                    return false;
                }

                // The Properties reference may have been demoted to a WeakReference.
                // If it was but is still retrievable re-promote it to a strong reference.
                if (null == Properties)
                {
                    Properties = _weakProperties.Target as IContactProperties;
                    // If it's been collected we won't use it.
                    if (null == Properties)
                    {
                        return false;
                    }
                }

                Assert.IsNotNull(Properties);

                // If this is being requested then restore the maximum time-to-live counter.
                // Ensure most-recently used properties are prioritized.
                _timeToLive = _CachePolicy.TimeToLiveCount;

                properties = Properties;
                return true;
            }
        public static WriteableContactProperties MakeWriteableCopy(IContactProperties properties)
        {
            Verify.IsNotNull(properties, "properties");

            // Can use the internal constructor so we don't unnecessarily dupe the stream.
            return new WriteableContactProperties(properties.SaveToStream(), true);
        }
示例#4
0
        /// <summary>Try to create a contact from a file.  Swallow reasonable exceptions.</summary>
        /// <param name="filePath">The file to load from</param>
        /// <param name="properties">The contact properties to return</param>
        /// <param name="lastModifiedUtc">Timestampe when the properties were last modified.</param>
        /// <returns></returns>
        private static bool _TryLoadPropertiesFromFile(string filePath, out IContactProperties properties, out DateTime lastModifiedUtc)
        {
            try
            {
                properties = _GetContactFromFile(filePath, out lastModifiedUtc);
                return true;
            }
            catch (FileNotFoundException) { }
            catch (InvalidDataException) { }
            catch (UnauthorizedAccessException) { }
            catch (Exception e)
            {
                // Really not expecting other failures here.  Potentially causes problems.
                Assert.Fail(e.ToString());
                throw;
            }

            lastModifiedUtc = default(DateTime);
            properties = null;
            return false;
        }
示例#5
0
        private bool _TryGetCachedFile(string normalizedPath, out IContactProperties properties)
        {
            Assert.AreEqual(normalizedPath, normalizedPath.ToUpperInvariant());

            properties = null;
            _CacheEntry entry;

            if (!_fileCache.TryGetValue(normalizedPath, out entry))
            {
                return false;
            }

            bool ret = entry.TryGetProperties(out properties);
            if (!ret)
            {
                _fileCache.Remove(normalizedPath);
            }

            return ret;
        }
示例#6
0
        /// <summary>Internal only constructor for Contact.</summary>
        /// <param name="manager"></param>
        /// <param name="properties"></param>
        /// <param name="fileName"></param>
        internal Contact(ContactManager manager, IContactProperties properties, string fileName)
        {
            Assert.IsNotNull(properties);
            Verify.IsNeitherNullNorEmpty(fileName, "fileName");

            // Caller should have ensured this is canonicalized...
            Assert.AreEqual(fileName, IOPath.GetFullPath(fileName));

            _manager = manager;
            _contactProperties = properties;
            _sharedProperties = true;
            _sourceHash = _contactProperties.StreamHash;
            _type = GetTypeFromExtension(fileName);
            Path = fileName;
            Id = ContactId.GetRuntimeId(ContactIds.Default.Value, Path);
            _originalName = Names.Default.FormattedName;
        }
示例#7
0
            /// <summary>Decrements the heart-beat timer for this.</summary>
            /// <returns>
            /// Whether this entry is still active.  False implies it's completely dead.
            /// </returns>
            public bool DecrementTimer()
            {
                --_timeToLive;
                if (_timeToLive <= 0)
                {
                    if (null != Properties)
                    {
                        // The entry hasn't been accessed for a fair amount of time.
                        // Can't forcibly clean up the resources held by the properties,
                        // but can demote the reference to be weak.
                        _weakProperties = new WeakReference(Properties);
                        Properties = null;
                    }

                    // If the garbage collector already cleared the properties then remove the entry.
                    return _weakProperties.IsAlive;
                }
                Assert.IsNotNull(Properties);
                return true;
            }
示例#8
0
        /// <summary>
        /// Internal only constructor for ContactManager.
        /// </summary>
        /// <param name="manager">The associated ContactManager instance.</param>
        /// <param name="type">The type of the contact to create.</param>
        /// <remarks>
        /// This allows the contacts returned by IContactCollection to be managed by this class.
        /// The manager is associated with the contact, which allows for Save to be called without
        /// the contact being initially backed by a path.
        /// </remarks>
        internal Contact(ContactManager manager, ContactTypes type)
        {
            Verify.IsApartmentState(ApartmentState.STA, _exceptionStringBadThreadId);
            if (!_IsValidSingleContactType(type, false))
            {
                throw new ArgumentException("The provided type must be of a legal single value (also not ContactTypes.None).", "type");
            }

            _manager = manager;

            _contactProperties = new WriteableContactPropertiesAlias();
            // The IContactProperties is disposable by this object.
            //_sharedProperties = false;

            // New contact, no file name associated with the Id.
            Id = ContactId.GetRuntimeId(ContactIds.Default.Value, null);
            // _path = null;

            _originalName = string.Empty;
            _type = type;

            // New contact, so no worries of conflicting changes on save.
            // _sourceHash = null;
        }
示例#9
0
        /// <summary>
        /// Load a contact from a stream.
        /// </summary>
        /// <param name="stream">The stream with the Contact contents to load.</param>
        /// <param name="type">
        /// The type of the contact to create.  ContactTypes.None is valid for this constructor.
        /// </param>
        /// <remarks>
        /// This is the only Contact constructor where ContactTypes.None is a valid type parameter.
        /// </remarks>
        public Contact(Stream stream, ContactTypes type)
        {
            Verify.IsNotNull(stream, "stream");
            Verify.IsApartmentState(ApartmentState.STA, _exceptionStringBadThreadId);
            if (!_IsValidSingleContactType(type, true))
            {
                throw new ArgumentException("ContactType must be a valid single value for this constructor (ContactTypes.None is OK).", "type");
            }

            _type = type;

            //
            // Default values are implicitly set by the runtime (CodeAnalysis tools flag unnecessary default initializations).
            //

            // Loading a contact from a stream, so there's no path and the user can't commit changes directly.
            // _sourceHash = null;
            // _path = null;
            // Shouldn't need this either (only used for Commit)
            // _originalName = null;

            stream.Position = 0;

            // No reason to assume that because we're being loaded from a stream that this
            // is going to be modified.  Go ahead and delay building the DOM.
            // CONSDIER: Adding a flag indicating intention to write.
            _contactProperties = new ReadonlyContactProperties(stream);

            // The IContactProperties is disposable by this object.
            //_sharedProperties = false;

            Id = ContactId.GetRuntimeId(ContactIds.Default.Value, null);
        }
示例#10
0
 private void _EnsureWriteableProperties()
 {
     if (_contactProperties.IsReadonly)
     {
         _contactProperties = WriteableContactPropertiesAlias.MakeWriteableCopy(_contactProperties);
         Assert.IsFalse(_contactProperties.IsReadonly);
     }
 }
示例#11
0
        /// <summary>
        /// Load a contact from a file.
        /// </summary>
        /// <param name="fileName">The file that contains the contact data to load.</param>
        /// <exception cref="InvalidDataException">
        /// The specified file exists but doesn't doesn't represent a valid contact.
        /// </exception>
        /// <exception cref="FileNotFoundException">
        /// The specified file couldn't be found.
        /// </exception>
        /// <exception cref="UnauthorizedAccessException">
        /// The specified file couldn't be opened for an unknown reason.  It may be that it's
        /// opened within incompatible sharing permissions.  Retrying the operation at a later
        /// time may succeed.
        /// </exception>
        public Contact(string fileName)
        {
            Verify.IsNotNull(fileName, "fileName");
            Verify.IsApartmentState(ApartmentState.STA, _exceptionStringBadThreadId);

            // make the path absolute.
            fileName = IOPath.GetFullPath(fileName);

            _contactProperties = ContactLoader.GetContactFromFile(fileName);
            _sharedProperties = true;

            // Only really need to compute the hash if we change the contact...
            _sourceHash = _contactProperties.StreamHash;
            Path = fileName;
            Id = ContactId.GetRuntimeId(ContactIds.Default.Value, Path);
            _originalName = Names.Default.FormattedName;
            _type = GetTypeFromExtension(fileName);
        }
示例#12
0
 /// <summary>
 /// Protected overload of Dispose that is standard in IDisposable patterns.
 /// </summary>
 /// <param name="disposing">Whether or not this is being called by Dispose, rather than by the finalizer.</param>
 /// <remarks>
 /// Overrides of this method should always call base.Dispose.
 /// </remarks>
 protected virtual void Dispose(bool disposing)
 {
     if (disposing)
     {
         // Only dispose of the IContactProperties if it's not potentially shared with others.
         // Otherwise set it to null and let the GC deal with it as it sees fit.
         if (!_sharedProperties)
         {
             var disposable = _contactProperties as IDisposable;
             Utility.SafeDispose(ref disposable);
         }
         _contactProperties = null;
     }
 }