Permalink
Browse files

Adding WebForms/Futures/GeneratedImage for the new Image Generation f…

…eature

git-svn-id: https://aspnet.svn.codeplex.com/svn@14652 e17a0e51-4ae3-4d35-97c3-1a29b211df97
  • Loading branch information...
SND\AspNetExtensions_cp SND\AspNetExtensions_cp
SND\AspNetExtensions_cp authored and SND\AspNetExtensions_cp committed Aug 19, 2008
1 parent ccbbd4f commit 33716769bbf30cbcd5f56c27778ccc525162fd6b
Showing with 4,919 additions and 0 deletions.
  1. +35 −0 WebForms/Futures/GeneratedImage/GeneratedImage.sln
  2. +6 −0 WebForms/Futures/GeneratedImage/GeneratedImage.vsmdi
  3. +86 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage.csproj
  4. +261 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/DiskImageStore.cs
  5. +133 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/GeneratedImage.cs
  6. +147 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/GeneratedImageDesigner.cs
  7. +103 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/ImageHandler.cs
  8. +193 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/ImageHandlerInternal.cs
  9. +31 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/ImageInfo.cs
  10. +62 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/ImageParameter.cs
  11. +212 −0 WebForms/Futures/GeneratedImage/GeneratedImage/GeneratedImage/ImageTransform.cs
  12. +38 −0 WebForms/Futures/GeneratedImage/GeneratedImage/Properties/AssemblyInfo.cs
  13. +114 −0 WebForms/Futures/GeneratedImage/GeneratedImage/Resources/WebResources.Designer.cs
  14. +166 −0 WebForms/Futures/GeneratedImage/GeneratedImage/Resources/WebResources.resx
  15. +77 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/ExceptionHelper.cs
  16. +103 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/GeneratedImage/GeneratedImageTest.cs
  17. +247 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/GeneratedImage/ImageHandlerTest.cs
  18. +38 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/GeneratedImage/ImageInfoTest.cs
  19. +18 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/GeneratedImage/ImageParameterTest.cs
  20. +78 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/GeneratedImage/ImageResizeTransformTest.cs
  21. +84 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/GeneratedImageTest.csproj
  22. +39 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/MoQ/Moq License.txt
  23. BIN WebForms/Futures/GeneratedImage/GeneratedImageTest/MoQ/Moq.dll
  24. BIN WebForms/Futures/GeneratedImage/GeneratedImageTest/MoQ/Moq.pdb
  25. +2,591 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/MoQ/Moq.xml
  26. +35 −0 WebForms/Futures/GeneratedImage/GeneratedImageTest/Properties/AssemblyInfo.cs
  27. +22 −0 WebForms/Futures/GeneratedImage/LocalTestRun.testrunconfig
@@ -0,0 +1,35 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9E773C6F-C4FC-465C-A440-785990777A41}"
+ ProjectSection(SolutionItems) = preProject
+ GeneratedImage.vsmdi = GeneratedImage.vsmdi
+ LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneratedImage", "GeneratedImage\GeneratedImage.csproj", "{CC4399BC-FC0A-4247-AAF5-17D9A6C24FF1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneratedImageTest", "GeneratedImageTest\GeneratedImageTest.csproj", "{316B8A23-C1B7-4009-A6C2-5F0D07F8DC00}"
+EndProject
+Global
+ GlobalSection(TestCaseManagementSettings) = postSolution
+ CategoryFile = GeneratedImage.vsmdi
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CC4399BC-FC0A-4247-AAF5-17D9A6C24FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CC4399BC-FC0A-4247-AAF5-17D9A6C24FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CC4399BC-FC0A-4247-AAF5-17D9A6C24FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CC4399BC-FC0A-4247-AAF5-17D9A6C24FF1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {316B8A23-C1B7-4009-A6C2-5F0D07F8DC00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {316B8A23-C1B7-4009-A6C2-5F0D07F8DC00}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {316B8A23-C1B7-4009-A6C2-5F0D07F8DC00}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {316B8A23-C1B7-4009-A6C2-5F0D07F8DC00}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
+ <TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
+ <RunConfiguration id="5a46a0e8-e5ee-436f-80f9-86b749968b00" name="Local Test Run" storage="localtestrun.testrunconfig" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, PublicKeyToken=b03f5f7f11d50a3a" />
+ </TestList>
+</TestLists>
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{CC4399BC-FC0A-4247-AAF5-17D9A6C24FF1}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Web</RootNamespace>
+ <AssemblyName>Microsoft.Web.GeneratedImage</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Design" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Net">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web" />
+ <Reference Include="System.Web.Abstractions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="GeneratedImage\DiskImageStore.cs" />
+ <Compile Include="GeneratedImage\GeneratedImage.cs" />
+ <Compile Include="GeneratedImage\ImageHandler.cs" />
+ <Compile Include="GeneratedImage\GeneratedImageDesigner.cs" />
+ <Compile Include="GeneratedImage\ImageHandlerInternal.cs" />
+ <Compile Include="GeneratedImage\ImageInfo.cs" />
+ <Compile Include="GeneratedImage\ImageParameter.cs" />
+ <Compile Include="GeneratedImage\ImageTransform.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Resources\WebResources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>WebResources.resx</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\WebResources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>WebResources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
@@ -0,0 +1,261 @@
+//#define INDIVIDUAL_LOCKS
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Web;
+using System.Web.Hosting;
+#if INDIVIDUAL_LOCKS
+using System.Collections;
+#endif
+
+namespace Microsoft.Web {
+ internal interface IImageStore {
+ void Add(string id, byte[] data);
+
+ bool TryTransmitIfContains(string id, HttpResponseBase response);
+ }
+
+ public class DiskImageStore : IImageStore {
+ private const string s_tempFileExtension = ".tmp";
+ private const string s_cacheAppRelativePath = @"~\App_Data\_imagecache\";
+ private static DiskImageStore s_instance;
+ private static object s_instanceLock = new object();
+ private static string _cachePath;
+
+ private DateTime _lastPurge;
+ private object _purgeQueuedLock = new object();
+ private bool _purgeQueued;
+ private static TimeSpan _purgeInterval;
+
+#if INDIVIDUAL_LOCKS
+ private Hashtable _fileLocks = new Hashtable();
+#else
+ private object _fileLock = new object();
+#endif
+
+ public static string CachePath {
+ get {
+ return _cachePath;
+ }
+ set {
+ if (String.IsNullOrEmpty(value)) {
+ throw new ArgumentNullException("value");
+ }
+ _cachePath = value;
+ }
+ }
+ public static bool EnableAutoPurge { get; set; } //turn on/off purge feature
+ public static TimeSpan PurgeInterval {
+ get {
+ return _purgeInterval;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+ if (value.Ticks < 0) {
+ throw new ArgumentOutOfRangeException("value");
+ }
+
+ _purgeInterval = value;
+ }
+ }
+
+ private DateTime LastPurge {
+ get {
+ if (_lastPurge == null) {
+ _lastPurge = DateTime.Now.Subtract(PurgeInterval);
+ }
+ return _lastPurge;
+ }
+ set {
+ _lastPurge = value;
+ }
+ }
+
+ static DiskImageStore() {
+ EnableAutoPurge = true;
+ PurgeInterval = new TimeSpan(0, 5, 0);
+ CachePath = HostingEnvironment.MapPath(s_cacheAppRelativePath);
+ }
+
+ internal DiskImageStore() {
+ // REVIEW: temporary hack to get unit tests running
+ if (CachePath != null && !Directory.Exists(CachePath)) {
+ Directory.CreateDirectory(CachePath);
+ }
+ _lastPurge = DateTime.Now;
+ }
+
+ internal static IImageStore Instance {
+ get {
+ if (s_instance == null) {
+ lock (s_instanceLock) {
+ if (s_instance == null) {
+ s_instance = new DiskImageStore();
+ }
+ }
+ }
+ return s_instance;
+ }
+ }
+
+ private void PurgeCallback(object target) {
+ var files = new DirectoryInfo(CachePath).GetFiles();
+ DateTime threshold = DateTime.Now.Subtract(PurgeInterval);
+ List<FileInfo> toTryDeleteAgain = new List<FileInfo>();
+ foreach (var fileinfo in files) {
+ if (fileinfo.CreationTime < threshold) {
+#if INDIVIDUAL_LOCKS
+ string id = GetEntryId(fileinfo);
+ object lockObject = GetFileLockObject(id);
+ if (lockObject != null) {
+ if (!Monitor.TryEnter(lockObject)) {
+ toTryDeleteAgain.Add(fileinfo);
+ continue;
+ }
+
+ try {
+ fileinfo.Delete();
+ DiscardFileLockObject(id);
+ }
+ catch (Exception) {
+ // do nothing
+ }
+ finally {
+ Monitor.Exit(lockObject);
+ }
+ }
+#else
+
+ try {
+ fileinfo.Delete();
+ } catch(Exception) {
+ toTryDeleteAgain.Add(fileinfo);
+ }
+#endif
+ }
+ }
+ Thread.Sleep(0);
+ foreach (var fileinfo in toTryDeleteAgain) {
+#if INDIVIDUAL_LOCKS
+ string id = GetEntryId(fileinfo);
+ object lockObject = GetFileLockObject(id);
+ if (!Monitor.TryEnter(lockObject)) {
+ continue;
+ }
+ try {
+ fileinfo.Delete();
+ DiscardFileLockObject(id);
+ }
+ catch (Exception) {
+ // do nothing, delete will be tried next time purge is called
+ }
+ finally {
+ Monitor.Exit(lockObject);
+ }
+#else
+ try {
+ fileinfo.Delete();
+ }
+ catch (Exception) {
+ // do nothing at this point, try to delete file during next purge
+ }
+#endif
+ }
+
+ LastPurge = DateTime.Now;
+ _purgeQueued = false;
+ }
+
+ private void Add(string id, byte[] data) {
+ string path = BuildFilePath(id);
+ lock (GetFileLockObject(id)) {
+ try {
+ File.WriteAllBytes(path, data);
+ }
+ catch (Exception) {
+ // REVIEW for now ignore any write problems
+ }
+ }
+ }
+
+ private bool TryTransmitIfContains(string id, HttpResponseBase response) {
+ if (EnableAutoPurge) {
+ QueueAutoPurge();
+ }
+ string path = BuildFilePath(id);
+ lock (GetFileLockObject(id)) {
+ if (File.Exists(path)) {
+ response.TransmitFile(path);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+ private void QueueAutoPurge() {
+ DateTime now = DateTime.Now;
+ if (!_purgeQueued && now.Subtract(LastPurge) > PurgeInterval) {
+ lock (_purgeQueuedLock) {
+ if (!_purgeQueued) {
+ _purgeQueued = true;
+ ThreadPool.QueueUserWorkItem(PurgeCallback);
+ }
+ }
+ }
+ }
+
+
+ private object GetFileLockObject(string id) {
+#if INDIVIDUAL_LOCKS
+ object lockObject = _fileLocks[id];
+
+ if (lockObject == null) {
+ // lock on the hashtable to prevent other writers
+ lock (_fileLocks) {
+ lockObject = new object();
+ _fileLocks[id] = lockObject;
+ }
+ }
+
+ return lockObject;
+#else
+ return _fileLock;
+#endif
+ }
+
+#if INDIVIDUAL_LOCKS
+ private static string GetEntryId(FileInfo fileinfo) {
+ string id = fileinfo.Name.Substring(0, fileinfo.Name.Length - s_tempFileExtension.Length);
+ return id;
+ }
+
+ private void DiscardFileLockObject(string id) {
+ // lock on hashtable to prevent other writers
+ lock (_fileLocks) {
+ _fileLocks.Remove(id);
+ }
+ }
+#endif
+
+ private static string BuildFilePath(string id) {
+ return CachePath + id + s_tempFileExtension;
+ }
+
+ #region IImageStore Members
+
+ void IImageStore.Add(string id, byte[] data) {
+ this.Add(id, data);
+ }
+
+ bool IImageStore.TryTransmitIfContains(string id, HttpResponseBase response) {
+ return this.TryTransmitIfContains(id, response);
+ }
+
+ #endregion
+ }
+}
Oops, something went wrong.

0 comments on commit 3371676

Please sign in to comment.