New test.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / TypeCacheUtil.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\r
5  * This software is subject to the Microsoft Public License (Ms-PL). \r
6  * A copy of the license can be found in the license.htm file included \r
7  * in this distribution.\r
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc {\r
14     using System;\r
15     using System.Collections;\r
16     using System.Collections.Generic;\r
17     using System.Diagnostics.CodeAnalysis;\r
18     using System.IO;\r
19     using System.Linq;\r
20     using System.Reflection;\r
21 \r
22     internal static class TypeCacheUtil {\r
23 \r
24         private static IEnumerable<Type> FilterTypesInAssemblies(IBuildManager buildManager, Predicate<Type> predicate) {\r
25             // Go through all assemblies referenced by the application and search for types matching a predicate\r
26             IEnumerable<Type> typesSoFar = Type.EmptyTypes;\r
27 \r
28             ICollection assemblies = buildManager.GetReferencedAssemblies();\r
29             foreach (Assembly assembly in assemblies) {\r
30                 Type[] typesInAsm;\r
31                 try {\r
32                     typesInAsm = assembly.GetTypes();\r
33                 }\r
34                 catch (ReflectionTypeLoadException ex) {\r
35                     typesInAsm = ex.Types;\r
36                 }\r
37                 typesSoFar = typesSoFar.Concat(typesInAsm);\r
38             }\r
39             return typesSoFar.Where(type => TypeIsPublicClass(type) && predicate(type));\r
40         }\r
41 \r
42         public static List<Type> GetFilteredTypesFromAssemblies(string cacheName, Predicate<Type> predicate, IBuildManager buildManager) {\r
43             TypeCacheSerializer serializer = new TypeCacheSerializer();\r
44 \r
45             // first, try reading from the cache on disk\r
46             List<Type> matchingTypes = ReadTypesFromCache(cacheName, predicate, buildManager, serializer);\r
47             if (matchingTypes != null) {\r
48                 return matchingTypes;\r
49             }\r
50 \r
51             // if reading from the cache failed, enumerate over every assembly looking for a matching type\r
52             matchingTypes = FilterTypesInAssemblies(buildManager, predicate).ToList();\r
53 \r
54             // finally, save the cache back to disk\r
55             SaveTypesToCache(cacheName, matchingTypes, buildManager, serializer);\r
56 \r
57             return matchingTypes;\r
58         }\r
59 \r
60         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",\r
61             Justification = "Cache failures are not fatal, and the code should continue executing normally.")]\r
62         internal static List<Type> ReadTypesFromCache(string cacheName, Predicate<Type> predicate, IBuildManager buildManager, TypeCacheSerializer serializer) {\r
63             try {\r
64                 using (Stream stream = buildManager.ReadCachedFile(cacheName)) {\r
65                     if (stream != null) {\r
66                         using (StreamReader reader = new StreamReader(stream)) {\r
67                             List<Type> deserializedTypes = serializer.DeserializeTypes(reader);\r
68                             if (deserializedTypes != null && deserializedTypes.All(type => TypeIsPublicClass(type) && predicate(type))) {\r
69                                 // If all read types still match the predicate, success!\r
70                                 return deserializedTypes;\r
71                             }\r
72                         }\r
73                     }\r
74                 }\r
75             }\r
76             catch {\r
77             }\r
78 \r
79             return null;\r
80         }\r
81 \r
82         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",\r
83             Justification = "Cache failures are not fatal, and the code should continue executing normally.")]\r
84         internal static void SaveTypesToCache(string cacheName, IList<Type> matchingTypes, IBuildManager buildManager, TypeCacheSerializer serializer) {\r
85             try {\r
86                 using (Stream stream = buildManager.CreateCachedFile(cacheName)) {\r
87                     if (stream != null) {\r
88                         using (StreamWriter writer = new StreamWriter(stream)) {\r
89                             serializer.SerializeTypes(matchingTypes, writer);\r
90                         }\r
91                     }\r
92                 }\r
93             }\r
94             catch {\r
95             }\r
96         }\r
97 \r
98         private static bool TypeIsPublicClass(Type type) {\r
99             return (type != null && type.IsPublic && type.IsClass && !type.IsAbstract);\r
100         }\r
101 \r
102     }\r
103 }\r