Logo Search packages:      
Sourcecode: f-spot version File versions

Cache.cs

using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace FlickrNet
{
      /// <summary>
      /// Internal Cache class
      /// </summary>
00012       internal sealed class Cache
      {
            private class CacheException : Exception
            {
                  public CacheException(string message) : base(message)
                  {}

            }

            private static PersistentCache _downloads;


            /// <summary>
            /// A static object containing the list of cached downloaded files.
            /// </summary>
            public static PersistentCache Downloads
00028             {
                  get 
                  {
                        lock(lockObject)
                        {
                              if( _downloads == null )
                                    _downloads = new PersistentCache(Path.Combine(CacheLocation, "downloadCache.dat"), new PictureCacheItemPersister(), CacheSizeLimit);
                              return _downloads;
                        }
                  }
            }

            private static PersistentCache _responses;

            /// <summary>
            /// A static object containing the list of cached responses from Flickr.
            /// </summary>
            public static PersistentCache Responses
00046             {
                  get 
                  {
                        lock(lockObject)
                        {
                              if( _responses == null )
                                    _responses = new PersistentCache(Path.Combine(CacheLocation, "responseCache.dat"), new ResponseCacheItemPersister(), CacheSizeLimit);
                              return _responses;
                        }
                  }
            }


            private Cache()
            {
            }

            private static object lockObject = new object();

            private enum Tristate
            {
                  Null, True, False
            }
            private static Tristate _cacheDisabled;

            internal static bool CacheDisabled
            {
                  get
                  {
                        if( _cacheDisabled == Tristate.Null && FlickrConfigurationManager.Settings != null )
                              _cacheDisabled = (FlickrConfigurationManager.Settings.CacheDisabled?Tristate.True:Tristate.False);
                        
                        if( _cacheDisabled == Tristate.Null ) _cacheDisabled = Tristate.False;

                        return (_cacheDisabled==Tristate.True);
                  }
                  set
                  {
                        _cacheDisabled = value?Tristate.True:Tristate.False;
                  }
            }

            private static string _cacheLocation;

            internal static string CacheLocation
            {
                  get 
                  { 
                        if( _cacheLocation == null && FlickrConfigurationManager.Settings != null )
                              _cacheLocation = FlickrConfigurationManager.Settings.CacheLocation;
                        if( _cacheLocation == null )
                        {
                              try
                              {
                                    _cacheLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "FlickrNet");
                              }
                              catch(System.Security.SecurityException)
                              {
                                    // Permission to read application directory not provided.
                                    throw new CacheException("Unable to read default cache location. Please cacheLocation in configuration file or set manually in code");
                              }
                        }

                        if( _cacheLocation == null )
                              throw new CacheException("Unable to determine cache location. Please set cacheLocation in configuration file or set manually in code");

                        return _cacheLocation;
                  }
                  set
                  {
                        _cacheLocation = value;
                  }
            }

            internal static long CacheSizeLimit
            {
                  get 
                  {
                        if( CacheSettings.ContainsKey("SizeLimit") )
                              return (long)CacheSettings["SizeLimit"];
                        else
                              return 50 * 1024 * 1024;
                  }
                  set 
                  { 
                        if( CacheSettings.ContainsKey("SizeLimit") )
                              CacheSettings["SizeLimit"] = value;
                        else
                              CacheSettings.Add("SizeLimit", value);
                  }
            }

            internal static long CacheSize
            {
                  get 
                  {
                        if( CacheSettings.ContainsKey("CurrentSize") )
                              return (long)CacheSettings["CurrentSize"];
                        else
                              return 0;
                  }
                  set 
                  { 
                        if( CacheSettings.ContainsKey("CurrentSize") )
                              CacheSettings["CurrentSize"] = value;
                        else
                              CacheSettings.Add("CurrentSize", value);
                  }
            }


            // Default cache timeout is 1 hour
            private static TimeSpan _cachetimeout = new TimeSpan(0, 1, 0, 0, 0);

            /// <summary>
            /// The default timeout for cachable objects within the cache.
            /// </summary>
            public static TimeSpan CacheTimeout
00164             {
                  get { return _cachetimeout; }
                  set { _cachetimeout = value; }
            }
            
            private static Hashtable _cacheSettings;

            private static Hashtable CacheSettings
            {
                  get
                  {
                        lock(lockObject)
                        {
                              if( _cacheSettings == null )
                                    LoadSettings();
                              return _cacheSettings;
                        }
                  }
            }

            private static void SaveSettings()
            {
                  System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

                  System.IO.Stream stream;

                  lock(CacheSettings.SyncRoot)
                  {
                        if( CacheLocation == null ) return;

                        stream = new FileStream(Path.Combine(CacheLocation, "cacheSettings.bin"), FileMode.OpenOrCreate, FileAccess.Write);
                        try
                        {
                              formatter.Serialize(stream, CacheSettings);
                        }
                        finally
                        {
                              stream.Close();
                        }
                  }
            }

            private static void LoadSettings()
            {
                  if( !Directory.Exists(CacheLocation) ) Directory.CreateDirectory(CacheLocation);

                  System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

                  System.IO.Stream stream = null;

                  if( CacheLocation != null ) 
                  {
                        stream = new FileStream(Path.Combine(CacheLocation, "cacheSettings.bin"), FileMode.OpenOrCreate);
                  }

                  if( stream == null )
                  {
                        _cacheSettings = new Hashtable();
                        return;
                  }
                  try
                  {
                        _cacheSettings = (Hashtable)formatter.Deserialize(stream);
                  }
                  catch(InvalidCastException)
                  {
                        _cacheSettings = new Hashtable();
                  }
                  catch(System.Runtime.Serialization.SerializationException)
                  {
                        _cacheSettings = new Hashtable();
                  }
                  finally
                  {
                        stream.Close();
                  }
            }

            internal static void FlushCache(string url)
            {
                  Responses[url] = null;
                  Downloads[url] = null;
            }

            internal static void FlushCache()
            {
                  Responses.Flush();
                  Downloads.Flush();
            }

      }

      /// <summary>
      /// A cache item containing details of a REST response from Flickr.
      /// </summary>
      [Serializable]
00260       public class ResponseCacheItem : ICacheItem
      {
            private string url;
            private string response;
            private DateTime creationTime;

            /// <summary>
            /// Gets or sets the original URL of the request.
            /// </summary>
00269             public string Url { get { return url; } set { url = value; } }

            /// <summary>
            /// Gets or sets the XML response.
            /// </summary>
00274             public string Response { get { return response; } set { response = value; } }

            /// <summary>
            /// Gets or sets the time the cache item was created.
            /// </summary>
00279             public DateTime CreationTime { get { return creationTime; } set { creationTime = value; } }

            /// <summary>
            /// Gets the filesize of the request.
            /// </summary>
00284             public long FileSize { get { return (response==null?0:response.Length); } }

00286             void ICacheItem.OnItemFlushed()
            {
            }

      }

      internal class ResponseCacheItemPersister : CacheItemPersister
      {
            public override ICacheItem Read(Stream inputStream)
            {
                  string s = Utils.ReadString(inputStream);
                  string response = Utils.ReadString(inputStream);

                  string[] chunks = s.Split('\n');

                  // Corrupted cache record, so throw IOException which is then handled and returns partial cache.
                  if( chunks.Length != 2 )
                        throw new IOException("Unexpected number of chunks found");

                  string url = chunks[0];
                  DateTime creationTime = new DateTime(long.Parse(chunks[1]));
                  ResponseCacheItem item = new ResponseCacheItem();
                  item.Url = url;
                  item.CreationTime = creationTime;
                  item.Response = response;
                  return item;
            }

            public override void Write(Stream outputStream, ICacheItem cacheItem)
            {
                  ResponseCacheItem item = (ResponseCacheItem) cacheItem;
                  StringBuilder result = new StringBuilder();
                  result.Append(item.Url + "\n");
                  result.Append(item.CreationTime.Ticks.ToString("0"));
                  Utils.WriteString(outputStream, result.ToString());
                  Utils.WriteString(outputStream, item.Response);
            }
      }

      /// <summary>
      /// An item that can be stored in a cache.
      /// </summary>
00328       public interface ICacheItem
      {
            /// <summary>
            /// The time this cache item was created.
            /// </summary>
00333             DateTime CreationTime { get; }

            /// <summary>
            /// Gets called back when the item gets flushed
            /// from the cache.
            /// </summary>
            void OnItemFlushed();

            /// <summary>
            /// The size of this item, in bytes. Return 0
            /// if size management is not important.
            /// </summary>
00345             long FileSize { get; }
      }

      /// <summary>
      /// An interface that knows how to read/write subclasses
      /// of ICacheItem.  Obviously there will be a tight
      /// coupling between concrete implementations of ICacheItem
      /// and concrete implementations of ICacheItemPersister.
      /// </summary>
00354       public abstract class CacheItemPersister
      {
            /// <summary>
            /// Read a single cache item from the input stream.
            /// </summary>
            public abstract ICacheItem Read(Stream inputStream);

            /// <summary>
            /// Write a single cache item to the output stream.
            /// </summary>
            public abstract void Write(Stream outputStream, ICacheItem cacheItem);
      }

      /// <summary>
      /// Contains details of image held with the Flickr.Net cache.
      /// </summary>
      [Serializable]
00371       public class PictureCacheItem : ICacheItem
      {
            #region [ Internal Variables ]
            internal string url;
            internal DateTime creationTime;
            internal string filename;
            internal long fileSize;
            #endregion

            #region [ Public Properties ]
            /// <summary>
            /// The URL of the original image on Flickr.
            /// </summary>
00384             public string Url { get { return url; } }
            /// <summary>
            /// The <see cref="DateTime"/> that the cache item was created.
            /// </summary>
00388             public DateTime CreationTime { get { return creationTime; } }

            /// <summary>
            /// The filesize in bytes of the image.
            /// </summary>
00393             public long FileSize { get { return fileSize; } }
            /// <summary>
            /// The Flickr photo id of the image.
            /// </summary>
            public string PhotoId
00398             {
                  get 
                  {
                        if( url == null ) 
                              return null;
                        else
                        {
                              int begin = url.LastIndexOf("/");
                              int end = url.IndexOf("_");

                              return url.Substring(begin + 1, (end - begin) - 1);
                        }
                  }
            }
            #endregion

            #region [ Public Methods ]

00416             void ICacheItem.OnItemFlushed()
            {
                  File.Delete(filename);
            }

            #endregion
      }

      /// <summary>
      /// Persists PictureCacheItem objects.
      /// </summary>
00427       internal class PictureCacheItemPersister : CacheItemPersister
      {
00429             public override ICacheItem Read(Stream inputStream)
            {
                  string s = Utils.ReadString(inputStream);

                  string[] chunks = s.Split('\n');
                  string url = chunks[0];
                  DateTime creationTime = new DateTime(long.Parse(chunks[1]));
                  string filename = chunks[2];
                  long fileSize = long.Parse(chunks[3]);

                  PictureCacheItem pci = new PictureCacheItem();
                  pci.url = url;
                  pci.creationTime = creationTime;
                  pci.filename = filename;
                  pci.fileSize = fileSize;
                  return pci;
            }

00447             public override void Write(Stream outputStream, ICacheItem cacheItem)
            {
                  PictureCacheItem pci = (PictureCacheItem) cacheItem;
                  StringBuilder output = new StringBuilder();

                  output.Append(pci.url + "\n");
                  output.Append(pci.creationTime.Ticks + "\n");
                  output.Append(pci.filename + "\n");
                  output.Append(pci.fileSize + "\n");

                  Utils.WriteString(outputStream, output.ToString());
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index