Merge pull request #82 from Unity-Technologies/master-gc-race
[mono.git] / mcs / class / System.Web.Extensions / System.Web.UI / CompositeScriptReference.cs
1 //
2 // Authors:
3 //   Marek Habersack <grendel@twistedcode.net>
4 //
5 // (C) 2011 Novell, Inc (http://novell.com/)
6 //
7
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 #if NET_3_5
29 using System;
30 using System.Collections;
31 using System.Collections.Concurrent;
32 using System.Collections.Generic;
33 using System.ComponentModel;
34 using System.IO;
35 using System.Reflection;
36 using System.Text;
37 using System.Web;
38 using System.Web.Handlers;
39 using System.Web.Hosting;
40
41 namespace System.Web.UI
42 {
43         [DefaultProperty ("Path")]
44         public class CompositeScriptReference : ScriptReferenceBase
45         {
46                 public const string COMPOSITE_SCRIPT_REFERENCE_PREFIX = "CSR:";
47
48                 static SplitOrderedList <string, List <CompositeEntry>> entriesCache;
49                 
50                 ScriptReferenceCollection scripts;
51                 
52                 [PersistenceMode (PersistenceMode.InnerProperty)]
53                 [Editor ("System.Web.UI.Design.CollectionEditorBase, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Design)]
54                 [MergableProperty (false)]
55                 [Category ("Behavior")]
56                 [DefaultValue (null)]
57                 [NotifyParentProperty (true)]   
58                 public ScriptReferenceCollection Scripts {
59                         get {
60                                 if (scripts == null)
61                                         scripts = new ScriptReferenceCollection ();
62                                 return scripts;
63                         }
64                 }
65
66                 static CompositeScriptReference ()
67                 {
68                         entriesCache = new SplitOrderedList <string, List <CompositeEntry>> (StringComparer.Ordinal);
69                 }
70
71                 internal static List <CompositeEntry> GetCompositeScriptEntries (string url)
72                 {
73                         if (String.IsNullOrEmpty (url) || entriesCache.Count == 0)
74                                 return null;
75                         
76                         List <CompositeEntry> ret;
77                         if (!entriesCache.Find ((uint)url.GetHashCode (), url, out ret))
78                                 return null;
79
80                         return ret;
81                 }
82                 
83                 protected internal override string GetUrl (ScriptManager scriptManager, bool zip)
84                 {
85                         if (scriptManager == null)
86                                 // .NET emulation...
87                                 throw new NullReferenceException (".NET emulation");
88                         
89                         var url = new StringBuilder (COMPOSITE_SCRIPT_REFERENCE_PREFIX);
90                         string path;
91                         string name;
92                         CompositeEntry entry;
93                         List <CompositeEntry> entries = null;
94                         WebResourceAttribute wra;
95                         
96                         foreach (ScriptReference sr in Scripts) {
97                                 if (sr == null)
98                                         continue;
99
100                                 name = sr.Name;
101                                 if (!String.IsNullOrEmpty (name)) {
102                                         Assembly assembly = sr.ResolvedAssembly;
103                                         name = GetScriptName (name, sr.IsDebugMode (scriptManager), null, assembly, out wra);
104                                         path = scriptManager.ScriptPath;
105                                         if (sr.IgnoreScriptPath || String.IsNullOrEmpty (path)) {
106                                                 entry = new CompositeEntry {
107                                                         Assembly = assembly,
108                                                         NameOrPath = name,
109                                                         Attribute = wra
110                                                 };
111                                         } else {
112                                                 AssemblyName an = assembly.GetName ();
113                                                 entry = new CompositeEntry {
114                                                         NameOrPath = String.Concat (VirtualPathUtility.AppendTrailingSlash (path), an.Name, '/', an.Version, '/', name),
115                                                         Attribute = wra
116                                                 };
117                                         }
118                                 } else if (!String.IsNullOrEmpty ((path = sr.Path))) {
119                                         bool notFound = false;
120                                         name = GetScriptName (path, sr.IsDebugMode (scriptManager), scriptManager.EnableScriptLocalization ? ResourceUICultures : null, null, out wra);
121                                         if (!HostingEnvironment.HaveCustomVPP)
122                                                 notFound = !File.Exists (HostingEnvironment.MapPath (name));
123                                         else 
124                                                 notFound = !HostingEnvironment.VirtualPathProvider.FileExists (name);
125
126                                         if (notFound)
127                                                 throw new HttpException ("Web resource '" + name + "' was not found.");
128                                         
129                                         entry = new CompositeEntry {
130                                                 NameOrPath = name
131                                         };
132                                 } else
133                                         entry = null;
134
135                                 if (entry != null) {
136                                         if (entries == null)
137                                                 entries = new List <CompositeEntry> ();
138                                         entries.Add (entry);
139                                         url.Append (entry.GetHashCode ().ToString ("x"));
140                                         entry = null;
141                                 }
142                         }
143                         
144                         if (entries == null || entries.Count == 0)
145                                 return String.Empty;
146
147                         string ret = ScriptResourceHandler.GetResourceUrl (ThisAssembly, url.ToString (), NotifyScriptLoaded);
148                         entriesCache.InsertOrUpdate ((uint)ret.GetHashCode (), ret, entries, entries);
149                         return ret;
150                 }
151 #if NET_4_0
152                 protected internal override bool IsAjaxFrameworkScript (ScriptManager scriptManager)
153                 {
154                         return false;
155                 }
156                 
157                 [Obsolete ("Use IsAjaxFrameworkScript(ScriptManager)")]
158 #endif
159                 protected internal override bool IsFromSystemWebExtensions ()
160                 {
161                         if (scripts == null || scripts.Count == 0)
162                                 return false;
163
164                         Assembly myAssembly = ThisAssembly;
165                         foreach (ScriptReference sr in scripts)
166                                 if (sr.ResolvedAssembly == myAssembly)
167                                         return true;
168
169                         return false;
170                 }
171
172                 internal bool HaveScripts ()
173                 {
174                         return (scripts != null && scripts.Count > 0);
175                 }
176         }
177 }
178 #endif