Fixing an issue with output parameters that are of type IntPtr
[castle.git] / MonoRail / Castle.MonoRail.Framework / Views / FileAssemblyViewSourceLoader.cs
blobdf44f84811d0bf4a090a9391c634876ce106d7db
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 using System.Text;
17 namespace Castle.MonoRail.Framework
19 using System;
20 using System.Collections;
21 using System.IO;
22 using Castle.MonoRail.Framework.Configuration;
23 using Castle.MonoRail.Framework.Views;
25 /// <summary>
26 /// Default <see cref="IViewSourceLoader"/> implementation
27 /// that uses the file system and assembly source as source of view templates
28 /// </summary>
29 public class FileAssemblyViewSourceLoader : IViewSourceLoader, IMRServiceEnabled
31 private readonly IList additionalSources = ArrayList.Synchronized(new ArrayList());
32 private bool enableCache = true;
33 private string viewRootDir;
34 private string virtualViewDir;
35 private FileSystemWatcher viewFolderWatcher;
37 /// <summary>
38 /// Creates a new instance
39 /// </summary>
40 public FileAssemblyViewSourceLoader()
44 ///<summary>
45 /// Creates a new instance with the viewRootDir
46 ///</summary>
47 public FileAssemblyViewSourceLoader(string viewRootDir)
49 this.viewRootDir = viewRootDir;
52 #region IMRServiceEnabled implementation
54 /// <summary>
55 /// Services the specified provider.
56 /// </summary>
57 /// <param name="provider">The provider.</param>
58 public void Service(IMonoRailServices provider)
60 IMonoRailConfiguration config = (IMonoRailConfiguration) provider.GetService(typeof(IMonoRailConfiguration));
62 if (config != null)
64 viewRootDir = config.ViewEngineConfig.ViewPathRoot;
65 virtualViewDir = config.ViewEngineConfig.VirtualPathRoot;
67 foreach(AssemblySourceInfo sourceInfo in config.ViewEngineConfig.Sources)
69 AddAssemblySource(sourceInfo);
74 #endregion
76 /// <summary>
77 /// Evaluates whether the specified template exists.
78 /// </summary>
79 /// <param name="sourceName">The template name</param>
80 /// <returns><c>true</c> if it exists</returns>
81 public bool HasSource(String sourceName)
83 if (HasTemplateOnFileSystem(sourceName))
85 return true;
88 return HasTemplateOnAssemblies(sourceName);
91 /// <summary>
92 /// Builds and returns a representation of a view template
93 /// </summary>
94 /// <param name="templateName">The template name</param>
95 /// <returns></returns>
96 public IViewSource GetViewSource(String templateName)
98 FileInfo fileInfo = CreateFileInfo(templateName);
100 if (fileInfo.Exists)
102 return new FileViewSource(fileInfo, enableCache);
104 else
106 return GetStreamFromAdditionalSources(templateName);
110 /// <summary>
111 /// Gets a list of views on the specified directory
112 /// </summary>
113 /// <param name="dirName">Directory name</param>
114 /// <param name="fileExtensionsToInclude">Optional fileExtensions to include in listing.</param>
115 /// <returns></returns>
116 public String[] ListViews(String dirName,params string[] fileExtensionsToInclude)
118 ArrayList views = new ArrayList();
120 CollectViewsOnFileSystem(dirName, views,fileExtensionsToInclude);
121 CollectViewsOnAssemblies(dirName, views);
123 return (String[]) views.ToArray(typeof(String));
126 /// <summary>
127 /// Gets/sets the root directory of views, obtained from the configuration.
128 /// </summary>
129 /// <value></value>
130 public string VirtualViewDir
132 get { return virtualViewDir; }
133 set { virtualViewDir = value; }
136 /// <summary>
137 /// Gets/sets the root directory of views,
138 /// obtained from the configuration.
139 /// </summary>
140 public string ViewRootDir
142 get { return viewRootDir; }
143 set { viewRootDir = value; }
146 /// <summary>
147 /// Gets or sets whether the instance should use cache
148 /// </summary>
149 /// <value></value>
150 public bool EnableCache
152 get { return enableCache; }
153 set { enableCache = value; }
156 /// <summary>
157 /// Gets a list of assembly sources
158 /// </summary>
159 /// <value></value>
160 public IList AssemblySources
162 get { return additionalSources; }
165 /// <summary>
166 /// Adds the assembly source.
167 /// </summary>
168 /// <param name="assemblySourceInfo">The assembly source info.</param>
169 public void AddAssemblySource(AssemblySourceInfo assemblySourceInfo)
171 additionalSources.Add(assemblySourceInfo);
174 #region Handle File System Changes To Views
176 /// <summary>
177 /// Raised when the view is changed.
178 /// </summary>
179 public event FileSystemEventHandler ViewChanged
183 //avoid concurrency problems with creating/removing the watcher
184 //in two threads in parallel. Unlikely, but better to be safe.
185 lock(this)
187 //create the watcher if it doesn't exists
188 if (viewFolderWatcher == null)
190 InitViewFolderWatch();
192 ViewChangedImpl += value;
195 remove
197 //avoid concurrency problems with creating/removing the watcher
198 //in two threads in parallel. Unlikely, but better to be safe.
199 lock(this)
201 ViewChangedImpl -= value;
202 if (ViewChangedImpl == null) //no more subscribers.
204 DisposeViewFolderWatch();
210 private event FileSystemEventHandler ViewChangedImpl = delegate { };
212 private void DisposeViewFolderWatch()
214 ViewChangedImpl -= (viewFolderWatcher_Changed);
215 if (viewFolderWatcher != null)
217 viewFolderWatcher.Dispose();
221 private void InitViewFolderWatch()
223 if (Directory.Exists(ViewRootDir))
225 viewFolderWatcher = new FileSystemWatcher(ViewRootDir);
226 viewFolderWatcher.IncludeSubdirectories = true;
227 viewFolderWatcher.Changed += (viewFolderWatcher_Changed);
228 viewFolderWatcher.Created += (viewFolderWatcher_Changed);
229 viewFolderWatcher.Deleted += (viewFolderWatcher_Changed);
230 viewFolderWatcher.Renamed += (viewFolderWatcher_Renamed);
231 viewFolderWatcher.EnableRaisingEvents = true;
235 private void viewFolderWatcher_Renamed(object sender, RenamedEventArgs e)
237 ViewChangedImpl(this, e);
240 private void viewFolderWatcher_Changed(object sender, FileSystemEventArgs e)
242 ViewChangedImpl(this, e);
245 #endregion
247 private bool HasTemplateOnFileSystem(string templateName)
249 return CreateFileInfo(templateName).Exists;
252 private FileInfo CreateFileInfo(string templateName)
254 if (Path.IsPathRooted(templateName))
256 templateName = templateName.Substring(Path.GetPathRoot(templateName).Length);
259 return new FileInfo(Path.Combine(viewRootDir, templateName));
262 private bool HasTemplateOnAssemblies(string templateName)
264 foreach(AssemblySourceInfo sourceInfo in additionalSources)
266 if (sourceInfo.HasTemplate(templateName))
268 return true;
272 return false;
275 private IViewSource GetStreamFromAdditionalSources(string templateName)
277 foreach(AssemblySourceInfo sourceInfo in additionalSources)
279 if (sourceInfo.HasTemplate(templateName))
281 return new EmbeddedResourceViewSource(templateName, sourceInfo);
285 return null;
288 private void CollectViewsOnFileSystem(string dirName, ArrayList views,params string[] fileExtensionsToInclude)
290 DirectoryInfo dir = new DirectoryInfo(Path.Combine(ViewRootDir, dirName));
291 if(!dir.Exists)
293 return; //early return
297 if(fileExtensionsToInclude ==null || fileExtensionsToInclude.Length==0)
299 fileExtensionsToInclude = new string[] {".*"};
302 foreach (string ext in fileExtensionsToInclude)
304 foreach (FileInfo file in dir.GetFiles("*" + ext))
306 views.Add(Path.Combine(dirName, file.Name));
312 private void CollectViewsOnAssemblies(string dirName, ArrayList views)
314 foreach(AssemblySourceInfo sourceInfo in additionalSources)
316 sourceInfo.CollectViews(dirName, views);