protected internal void RefreshResource(Resource resource, string encoding) { if (resource.RequiresChecking()) { resource.Touch(); if (resource.IsSourceModified()) { if (!resource.Encoding.Equals(encoding)) { this.rsvc.Error(string.Concat(new string[] { "Declared encoding for template '", resource.Name, "' is different on reload. Old = '", resource.Encoding, "' New = '", encoding })); resource.Encoding = encoding; } long lastModified = resource.ResourceLoader.GetLastModified(resource); resource.Process(); resource.LastModified = lastModified; } } }
/// <summary> Takes an existing resource, and 'refreshes' it. This /// generally means that the source of the resource is checked /// for changes according to some cache/check algorithm /// and if the resource changed, then the resource data is /// reloaded and re-parsed. /// * /// </summary> /// <param name="resource">resource to refresh /// * /// @throws ResourceNotFoundException if template not found /// from current source for this Resource /// @throws ParseErrorException if template cannot be parsed due /// to syntax (or other) error. /// @throws Exception if a problem in parse /// /// </param> /// <param name="encoding"></param> protected internal void RefreshResource(Resource resource, String encoding) { /* * The resource knows whether it needs to be checked * or not, and the resource's loader can check to * see if the source has been modified. If both * these conditions are true then we must reload * the input stream and parse it to make a new * AST for the resource. */ if (resource.RequiresChecking()) { /* * touch() the resource to reset the counters */ resource.Touch(); if (resource.IsSourceModified()) { /* * now check encoding info. It's possible that the newly declared * encoding is different than the encoding already in the resource * this strikes me as bad... */ if (!resource.Encoding.Equals(encoding)) { runtimeServices.Error( string.Format("Declared encoding for template '{0}' is different on reload. Old = '{1}' New = '{2}", resource.Name, resource.Encoding, encoding)); resource.Encoding = encoding; } /* * read how old the resource is _before_ * processing (=>reading) it */ long howOldItWas = resource.ResourceLoader.GetLastModified(resource); /* * read in the fresh stream and parse */ resource.Process(); /* * now set the modification info and reset * the modification check counters */ resource.LastModified = howOldItWas; } } }
/// <summary> Takes an existing resource, and 'refreshes' it. This /// generally means that the source of the resource is checked /// for changes according to some cache/check algorithm /// and if the resource changed, then the resource data is /// reloaded and re-parsed. /// * /// </summary> /// <param name="resource">resource to refresh /// * /// @throws ResourceNotFoundException if template not found /// from current source for this Resource /// @throws ParseErrorException if template cannot be parsed due /// to syntax (or other) error. /// @throws Exception if a problem in parse /// /// </param> protected internal virtual void refreshResource(Resource resource, System.String encoding) { /* * The resource knows whether it needs to be checked * or not, and the resource's loader can check to * see if the source has been modified. If both * these conditions are true then we must reload * the input stream and parse it to make a new * AST for the resource. */ if (resource.RequiresChecking()) { /* * touch() the resource to reset the counters */ resource.Touch(); if (resource.IsSourceModified()) { /* * now check encoding info. It's possible that the newly declared * encoding is different than the encoding already in the resource * this strikes me as bad... */ if (!resource.Encoding.Equals(encoding)) { rsvc.error("Declared encoding for template '" + resource.Name + "' is different on reload. Old = '" + resource.Encoding + "' New = '" + encoding); resource.Encoding = encoding; } /* * read how old the resource is _before_ * processing (=>reading) it */ long howOldItWas = resource.ResourceLoader.getLastModified(resource); /* * read in the fresh stream and parse */ resource.Process(); /* * now set the modification info and reset * the modification check counters */ resource.LastModified = howOldItWas; } } }
/// <summary> Gets the named resource. Returned class type corresponds to specified type (i.e. <code>Template</code> to <code> /// RESOURCE_TEMPLATE</code>). /// /// This method is now unsynchronized which requires that ResourceCache /// implementations be thread safe (as the default is). /// /// </summary> /// <param name="resourceName"> The name of the resource to retrieve. /// </param> /// <param name="resourceType"> The type of resource (<code>RESOURCE_TEMPLATE</code>, <code>RESOURCE_CONTENT</code>, etc.). /// </param> /// <param name="encoding"> The character encoding to use. /// /// </param> /// <returns> Resource with the template parsed and ready. /// /// </returns> /// <throws> ResourceNotFoundException if template not found from any available source. </throws> /// <throws> ParseErrorException if template cannot be parsed due to syntax (or other) Error. </throws> /// <throws> Exception if a problem in parse </throws> public virtual Resource GetResource(string resourceName, int resourceType, string encoding) { /* * Check to see if the resource was placed in the cache. * If it was placed in the cache then we will use * the cached version of the resource. If not we * will load it. * * Note: the type is included in the key to differentiate ContentResource * (static content from #include) with a Template. */ string resourceKey = resourceType + resourceName; Resource resource = globalCache.Get(resourceKey); if (resource != null) { try { // avoids additional method call to refreshResource if (resource.RequiresChecking()) { /* * both loadResource() and refreshResource() now return * a new Resource instance when they are called * (Put in the cache when appropriate) in order to allow * several threads to parse the same template simultaneously. * It is redundant work and will cause more garbage collection but the * benefit is that it allows concurrent parsing and processing * without race conditions when multiple requests try to * refresh/load the same template at the same time. * * Another alternative is to limit template parsing/retrieval * so that only one thread can parse each template at a time * but that creates a scalability bottleneck. * * See VELOCITY-606, VELOCITY-595 and VELOCITY-24 */ resource = RefreshResource(resource, encoding); } } catch (ResourceNotFoundException) { /* * something exceptional happened to that resource * this could be on purpose, * so clear the cache and try again */ globalCache.Remove(resourceKey); return(GetResource(resourceName, resourceType, encoding)); } catch (ParseErrorException pee) { log.Error("ResourceManager.getResource() exception", pee); throw pee; } catch (System.SystemException re) { log.Error("ResourceManager.getResource() exception", re); throw re; } catch (System.Exception e) { log.Error("ResourceManager.getResource() exception", e); throw e; } } else { try { /* * it's not in the cache, so load it. */ resource = LoadResource(resourceName, resourceType, encoding); if (resource.ResourceLoader.CachingOn) { globalCache.Put(resourceKey, resource); } } catch (ResourceNotFoundException rnfe) { log.Error("ResourceManager : unable to find resource '" + resourceName + "' in any resource loader."); throw rnfe; } catch (ParseErrorException pee) { log.Error("ResourceManager.getResource() parse exception", pee); throw pee; } catch (System.SystemException re) { log.Error("ResourceManager.getResource() load exception", re); throw re; } catch (System.Exception e) { log.Error("ResourceManager.getResource() exception new", e); throw e; } } return(resource); }