public void RenderCSS(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources, bool compress, bool includeImages, IEnumerable<IImageResource> parentIncludedImages)
		{
			if (_compress.HasValue)
				compress = _compress.Value;

			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);

			IEnumerable<IImageResource> includedImages = includeImages ? ExtendIncludedImages(parentIncludedImages) : null;

			if (_builds != null)
				foreach (ICSSResource resource in _builds)
					RenderBuild(resource, writer, urlFactory, writtenResources, compress, includeImages, includedImages);

			if (_includes != null)
				foreach (ICSSResource resource in _includes)
					resource.RenderCSS(writer, urlFactory, writtenResources, compress, includeImages, includedImages);

			if (writer == null || !_hasContent) return;

			var r = new StreamReader(_location.GetStream());
			var s = r.ReadToEnd();
			r.Close();
			if (compress)
				s = compressor.Compress(s);

			s = CSSUrlParser.ConvertUrls(s, Location, urlFactory, includedImages);

			writer.Write(s);
		}
		public virtual void RenderReferenceTags(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			// TODO: Render object tag
			//writer.Write("<img src=\"");
			//writer.Write(HttpUtility.HtmlEncode(urlFactory.GetURL(this)));
			//writer.Write("\" alt=\"\" />");
		}
		public void RenderReferenceTags(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);
			if (writer == null) return;
			writer.Write("<!-- Unknown Resource Type (");
			writer.Write(urlFactory.GetURL(this));
			writer.Write(") -->");
		}
		public void RenderProxy(Stream stream, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			FileLocation location = Location as FileLocation;
			using (Stream s = location.GetStream())
			{
				byte[] buffer = new byte[0x1000];
				int i;
				while ((i = s.Read(buffer, 0, buffer.Length)) > 0)
					stream.Write(buffer, 0, i);
			}
		}
		public virtual void RenderReferenceTags(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);
			if (_includedResources != null)
				foreach (IResource r in _includedResources)
					r.RenderReferenceTags(null, null, writtenResources);

			if (_package != null)
				_package.RenderReferenceTags(writer, urlFactory, writtenResources);
		}
		public void RenderReferenceTags(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);
			if (_references != null)
				foreach (IResource reference in _references)
					reference.RenderReferenceTags(writer, urlFactory, writtenResources);

			if (writer == null || !_hasContent) return;
			writer.Write("<link rel=\"stylesheet\" href=\"");
			writer.Write(HttpUtility.HtmlEncode(urlFactory.GetURL(this)));
			writer.Write("\" type=\"text/css\"/>");
		}
		public void RenderReferenceTags(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);
			if (_references != null)
				foreach (IResource reference in _references)
					reference.RenderReferenceTags(writer, urlFactory, writtenResources);

			if (writer == null || !_hasContent) return;
			writer.Write("<script src=\"");
			writer.Write(HttpUtility.HtmlEncode(urlFactory.GetURL(this)));
			writer.WriteLine("\" type=\"text/javascript\"></script>");
		}
		public void RenderJavaScript(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources, bool compress)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);

			var r = new StreamReader(_location.GetStream());
			var s = r.ReadToEnd();
			r.Close();
			if (compress)
			{
				s = compressor.Compress(s);
			}
			writer.Write(s);
		}
		public static string ConvertUrls(string css, IResourceLocation baseLocation, IResourceURLFactory urlFactory, IEnumerable<IImageResource> includedImages)
		{
			return _urlParser.Replace(css, m =>
			{
				string assembly = m.Groups[2].Success ? m.Groups[1].Value : null;
				string filename = m.Groups[2].Success ? m.Groups[2].Value : m.Groups[1].Value;
				IResourceLocation location = ResourceLocations.GetLocation(baseLocation, assembly, filename);
				if (location == null) return m.Groups[0].Value;
				if (includedImages != null)
					foreach (IImageResource res in includedImages)
						if (location.Equals(res.Location))
							return GetBase64URL(res);
				return urlFactory.GetURL(new UnknownResource(location));
			});
		}
		public void RenderCSS(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources, bool compress, bool includeImages, IEnumerable<IImageResource> parentIncludedImages)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);

			var r = new StreamReader(_location.GetStream());
			var s = r.ReadToEnd();
			r.Close();
			if (compress)
			{
				s = compressor.Compress(s);
			}
			s = CSSUrlParser.ConvertUrls(s, Location, urlFactory, includeImages ? parentIncludedImages : null);
			writer.Write(s);
		}
		public RoutingResourceHttpHandler(RequestContext context)
		{
			var values = context.RouteData.Values;

			var assembly = (values["assembly"] as string) ?? context.HttpContext.Request.QueryString["assembly"];
			var path = ((values["name"] ?? values["path"]) as string) ?? context.HttpContext.Request.QueryString["name"];

			if (assembly != null)
				location = ResourceLocations.GetAssemblyLocation(Assembly.Load(assembly), path);
			else
				location = new VirtualPathLocation("~/", path);

			version = (context.RouteData.Values["version"] as string) ?? context.HttpContext.Request.QueryString["version"];
			culture = (context.RouteData.Values["culture"] as string) ?? context.HttpContext.Request.QueryString["culture"];
			cultureUI = (context.RouteData.Values["cultureUI"] as string) ?? context.HttpContext.Request.QueryString["cultureUI"];

			urlFactory = new RoutingResourceURLFactory(context.RouteData.Route, context);
		}
		public void RenderJavaScript(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources, bool compress = false)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);

			if (writer == null) return;

			var r = new StreamReader(_location.GetStream());
			var s = r.ReadToEnd();

            var n = _location.FileName;
            if (n.EndsWith(".html", StringComparison.InvariantCultureIgnoreCase))
                n = n.Substring(0, n.Length - 5);

            n = "Html." + n;

            string[] names = n.Split('.');
            StringBuilder fullName = new StringBuilder();
            for (int i = 0; i < names.Length - 1; i++)
            {
                if (i > 0) fullName.Append('.');
                fullName.Append(names[i]);
                string fn = fullName.ToString();
                writer.Write("if(typeof(");
                writer.Write(fn);
                writer.Write(")!='object'||");
                writer.Write(fn);
                writer.Write("==null)");
                if (i == 0)
                    writer.Write("var ");
                writer.Write(fn);
                writer.Write("={};");
            }

            s = s.Replace("\\", "\\\\").Replace("'", "\'").Replace("\r", "").Replace("\n", "\\\n");
            s = n + " = '" + s + "';";

            r.Close();

			writer.Write(s);
		}
		private void RenderBuild(ICSSResource resource, TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources, bool compress, bool includeImages, IEnumerable<IImageResource> parentIncludedImages)
		{
			if (resource.References != null)
				foreach (IResource res in resource.References)
				{
					ICSSResource css = res as ICSSResource;
					if (css != null)
						RenderBuild(css, writer, urlFactory, writtenResources, compress, includeImages, parentIncludedImages);
				}
			resource.RenderCSS(writer, urlFactory, writtenResources, compress, includeImages, parentIncludedImages);
		}
		public void RenderProxyWithBase64(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			RenderCSS(writer, urlFactory, writtenResources, _defaultCompress, true, null);
		}
		public static void ProcessRequest(HttpRequest request, HttpResponse response, IResourceURLFactory urlFactory, IResource res, string version)
		{
			if (res == null) throw new HttpException(404, "Resource not found");

			IProxyResource r = res as IProxyResource;
			if (r == null) throw new Exception("Resource is not a IProxyResource.");

			if (version != null && request.Headers["If-None-Match"] == version)
			{
				response.Cache.VaryByHeaders["If-None-Match"] = true;
				response.StatusCode = 304;
				return;
			}

			response.ContentType = r.ContentType;

			if (version != null) response.Cache.SetETag(version);
			response.Cache.VaryByHeaders["Accept-Encoding"] = true;
			response.Cache.VaryByParams["*"] = true;
			response.Cache.SetVaryByCustom("browser");
			response.Cache.SetOmitVaryStar(true);

			response.Cache.SetCacheability(HttpCacheability.Public);
			response.Cache.SetExpires(DateTime.Now.AddYears(1));
			response.Cache.SetMaxAge(new TimeSpan(365, 0, 0, 0));
			response.Cache.SetValidUntilExpires(true);

			ICollection<IResource> writtenResources = new Collection<IResource>();
			

			bool base64support = !"IE".Equals(request.Browser.Browser, StringComparison.InvariantCultureIgnoreCase) || request.Browser.MajorVersion > 8;
			ITextProxyResource tr;
			IBase64TextProxyResource cr;

			string enc = request.Headers["Accept-Encoding"];
			if ((tr = r as ITextProxyResource) != null && tr.Gzip && enc != null && (enc.IndexOf("gzip") != -1 || request.Headers["---------------"] != null) && request.UserAgent.IndexOf("MSIE 6.") == -1)
			{
				enc = enc.IndexOf("x-gzip") != -1 ? "x-gzip" : "gzip";
				response.AppendHeader("Content-Encoding", enc);

				using (Stream compressionStream = new GZipStream(response.OutputStream, CompressionMode.Compress))
				using (TextWriter writer = new StreamWriter(compressionStream, Encoding.UTF8))
					if (base64support && (cr = tr as IBase64TextProxyResource) != null)
						cr.RenderProxyWithBase64(writer, urlFactory, writtenResources);
					else
						tr.RenderProxy(writer, urlFactory, writtenResources);
			}
			else if (base64support && (cr = tr as IBase64TextProxyResource) != null)
				cr.RenderProxyWithBase64(response.Output, urlFactory, writtenResources);
			else if (tr != null)
				tr.RenderProxy(response.Output, urlFactory, writtenResources);
			else
				r.RenderProxy(response.OutputStream, urlFactory, writtenResources);
		}
		public void RenderProxy(Stream stream, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			RenderProxy(new StreamWriter(stream), urlFactory, writtenResources);
		}
		public void RenderProxy(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			RenderJavaScript(writer, urlFactory, writtenResources, true);
		}
		public void RenderJavaScript(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources, bool compress)
		{
			CultureInfo culture = CultureInfo.CurrentUICulture;

			// Create namespace
			string bn = Manager.BaseName;
			string[] names = bn.Split('.');
			StringBuilder fullName = new StringBuilder();
			for(int i = 0; i < names.Length - 1; i++)
			{
				if (i > 0) fullName.Append('.');
				fullName.Append(names[i]);
				string fn = fullName.ToString();
				writer.Write("if(typeof(");
				writer.Write(fn);
				writer.Write(")!='object'||");
				writer.Write(fn);
				writer.Write("==null)");
				if (i == 0)
					writer.Write("var ");
				writer.Write(fn);
				writer.Write("={};");
			}

			// Write resources
			writer.Write(bn);
			writer.Write("={");

			List<int> addedKeyHashes = new List<int>();

			bool f = true;
			while(true)
			{
				System.Resources.ResourceSet set = Manager.GetResourceSet(culture, true, false);
				if (set != null)
				{
					System.Collections.IDictionaryEnumerator en = set.GetEnumerator();
					while (en.MoveNext())
					{
						if (en.Key is string && en.Value is string)
						{
							int hash = en.Key.GetHashCode();
							if (addedKeyHashes.Contains(hash)) continue;
							addedKeyHashes.Add(hash);
							if (f) f = false; else writer.Write(',');
							WriteJSEncodedString(writer, (string)en.Key);
							writer.Write(':');
							WriteJSEncodedString(writer, (string)en.Value);
						}
					}
				}
				if (culture == CultureInfo.InvariantCulture) break;
				culture = culture.Parent;
			}
			writer.Write("};");
		}
		public void RenderReferenceTags(TextWriter writer, IResourceURLFactory urlFactory, ICollection<IResource> writtenResources)
		{
			if (writtenResources.Contains(this)) return;
			writtenResources.Add(this);

			if (_builds != null)
				foreach (IResource resource in _builds)
				{
					resource.RenderReferenceTags(null, null, writtenResources);
					IProxyResource pr = resource as IProxyResource;
					if (pr != null)
					{
						if (pr.CultureSensitive) CultureSensitive = true;
						if (pr.CultureUISensitive) CultureUISensitive = true;
					}
				}

			if (_includes != null)
				foreach (IResource resource in _includes)
				{
					if (writtenResources.Contains(resource)) continue;
					writtenResources.Add(resource);
					if (resource.References != null)
						foreach (IResource res in resource.References)
							res.RenderReferenceTags(writer, urlFactory, writtenResources);
					IProxyResource pr = resource as IProxyResource;
					if (pr != null)
					{
						if (pr.CultureSensitive) CultureSensitive = true;
						if (pr.CultureUISensitive) CultureUISensitive = true;
					}
				}

			if (_references != null)
				foreach (IResource reference in _references)
					reference.RenderReferenceTags(writer, urlFactory, writtenResources);

			if (writer == null || (!_hasContent && _builds == null && _includes == null)) return;
			writer.Write("<link rel=\"stylesheet\" href=\"");
			writer.Write(HttpUtility.HtmlEncode(urlFactory.GetURL(this)));
			writer.Write("\" type=\"text/css\"/>");
		}