264 lines
7.9 KiB
C#
264 lines
7.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using ln.templates;
|
|
using System.Collections;
|
|
using ln.types;
|
|
|
|
namespace ln.http.resources
|
|
{
|
|
|
|
public delegate Resource ResourceTypeHookDelegate(DirectoryResource directoryResource, FileInfo fileInfo);
|
|
|
|
public class DirectoryResource : Resource, TemplateProvider
|
|
{
|
|
public ResourceTypeHookDelegate ResourceTypeHook { get; set; }
|
|
|
|
protected Dictionary<string, Resource> cache = new Dictionary<string, Resource>();
|
|
protected Dictionary<string, Resource> injectedResources = new Dictionary<string, Resource>();
|
|
|
|
IEnumerable<string> searchPaths;
|
|
|
|
public DirectoryResource(IEnumerable<string> search)
|
|
: base("")
|
|
{
|
|
searchPaths = search;
|
|
}
|
|
public DirectoryResource(Resource container,IEnumerable<string> search)
|
|
: base(container, System.IO.Path.GetFileName(search.First()))
|
|
{
|
|
searchPaths = search;
|
|
}
|
|
|
|
public DirectoryResource(String path)
|
|
: base("")
|
|
{
|
|
searchPaths = new string[] { path };
|
|
}
|
|
public DirectoryResource(String path,string name)
|
|
: base(name)
|
|
{
|
|
searchPaths = new string[] { path };
|
|
}
|
|
public DirectoryResource(Resource container, String path)
|
|
: base(container, System.IO.Path.GetFileName(path))
|
|
{
|
|
searchPaths = new string[] { path };
|
|
|
|
if (container is DirectoryResource)
|
|
{
|
|
DirectoryResource parent = container as DirectoryResource;
|
|
ResourceTypeHook = parent.ResourceTypeHook;
|
|
}
|
|
}
|
|
|
|
public override bool Contains(string name)
|
|
{
|
|
if (injectedResources.ContainsKey(name))
|
|
return true;
|
|
|
|
String cPath = PathHelper.FindPath(searchPaths.Select((p) => System.IO.Path.Combine(p, name)));
|
|
lock (cache)
|
|
{
|
|
if ((cPath == null) && cache.ContainsKey(name))
|
|
cache.Remove(name);
|
|
}
|
|
return (cPath != null);
|
|
|
|
}
|
|
|
|
public override void AddResource(Resource resource)
|
|
{
|
|
lock (cache)
|
|
{
|
|
cache.Add(resource.Name, resource);
|
|
}
|
|
}
|
|
|
|
public override void RemoveResource(Resource resource)
|
|
{
|
|
lock (cache)
|
|
{
|
|
if (cache.ContainsValue(resource))
|
|
cache.Remove(resource.Name);
|
|
}
|
|
}
|
|
|
|
public void InjectResource(Resource resource)
|
|
{
|
|
injectedResources.Add(resource.Name, resource);
|
|
}
|
|
|
|
public override Resource GetResource(string name)
|
|
{
|
|
lock (cache)
|
|
{
|
|
if (!Contains(name))
|
|
return null;
|
|
|
|
if (injectedResources.ContainsKey(name))
|
|
return injectedResources[name];
|
|
|
|
if (cache.ContainsKey(name))
|
|
return cache[name];
|
|
|
|
String cPath = PathHelper.FindPath(searchPaths.Select((p) => System.IO.Path.Combine(p, name)));
|
|
if (cPath == null)
|
|
return null;
|
|
|
|
if (Directory.Exists(cPath))
|
|
{
|
|
DirectoryResource child = new DirectoryResource(this, searchPaths.Select((p) => System.IO.Path.Combine(p, name)));
|
|
child.ResourceTypeHook = ResourceTypeHook;
|
|
return child;
|
|
}
|
|
else if (File.Exists(cPath))
|
|
{
|
|
FileInfo fileInfo = new FileInfo(cPath);
|
|
|
|
Resource resource = null;
|
|
if (ResourceTypeHook != null)
|
|
{
|
|
resource = ResourceTypeHook(this, fileInfo);
|
|
}
|
|
if (resource == null)
|
|
{
|
|
resource = new FileResource(this, fileInfo);
|
|
}
|
|
return resource;
|
|
}
|
|
}
|
|
return GetFallBackResource();
|
|
}
|
|
|
|
public override IEnumerable<Resource> GetResources()
|
|
{
|
|
return searchPaths.SelectMany((p) => new DirectoryInfo(p).EnumerateFileSystemInfos().Select((x) => GetResource(x.Name))).Distinct();
|
|
}
|
|
|
|
public override HttpResponse GetResponse(HttpRequest httpRequest)
|
|
{
|
|
if (DefaultResource != null)
|
|
return httpRequest.Redirect(String.Join("/", DefaultResource.Path));
|
|
|
|
Resource fallback = GetFallBackResource();
|
|
if (fallback != null)
|
|
{
|
|
return fallback.GetResponse(httpRequest);
|
|
}
|
|
else
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
public Template FindTemplate(string templatePath)
|
|
{
|
|
if ((templatePath[0] == '/') && (Container is DirectoryResource))
|
|
{
|
|
return RootDirectoryResource.FindTemplate(templatePath);
|
|
}
|
|
Resource current = this;
|
|
Queue<String> path = new Queue<string>(templatePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries));
|
|
while (path.Count > 0)
|
|
{
|
|
current = current.GetResource(path.Dequeue());
|
|
}
|
|
if (current is TemplateResource)
|
|
{
|
|
return (current as TemplateResource).Template;
|
|
}
|
|
|
|
if (Container is TemplateProvider)
|
|
{
|
|
return (Container as TemplateProvider).FindTemplate(templatePath);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public DirectoryResource RootDirectoryResource
|
|
{
|
|
get
|
|
{
|
|
if (Container is DirectoryResource)
|
|
{
|
|
DirectoryResource parent = Container as DirectoryResource;
|
|
return parent.RootDirectoryResource;
|
|
}
|
|
return this;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public class FileResource : DirectoryResource
|
|
{
|
|
|
|
DirectoryResource DirectoryResource { get; }
|
|
|
|
public FileInfo FileInfo { get; }
|
|
|
|
public FileResource(DirectoryResource directoryResource,FileInfo fileInfo)
|
|
:base(directoryResource,fileInfo.Name)
|
|
{
|
|
DirectoryResource = directoryResource;
|
|
FileInfo = fileInfo;
|
|
}
|
|
|
|
public override bool Contains(string name)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public override void AddResource(Resource resource)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override void RemoveResource(Resource resource)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override IEnumerable<Resource> GetResources()
|
|
{
|
|
return new Resource[0];
|
|
}
|
|
|
|
public override HttpResponse GetResponse(HttpRequest httpRequest)
|
|
{
|
|
if (!httpRequest.Method.Equals("GET"))
|
|
throw new NotImplementedException(String.Format("Method {0} is not supported by this resource", httpRequest.Method));
|
|
|
|
HttpResponse response = new HttpResponse(httpRequest, FileInfo.OpenRead());
|
|
|
|
response.SetHeader("content-type", GuessContentType());
|
|
|
|
return response;
|
|
}
|
|
|
|
public string GuessContentType()
|
|
{
|
|
String ext = FileInfo.Extension;
|
|
|
|
switch (ext)
|
|
{
|
|
case ".html":
|
|
return "text/html";
|
|
case ".txt":
|
|
return "text/plain";
|
|
case ".css":
|
|
return "text/css";
|
|
case ".js":
|
|
return "text/javascript";
|
|
default:
|
|
return "application/octet-stream";
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|