RE: Publication date
"Marc Cardle" <[email protected]>
| Newsgroups | gmane.comp.cms.jahia.template |
|---|---|
| Message-ID | <[email protected]> |
Ghislain,
In order to apply my aforementioned modifications to the Jahia 5.0s
org.jahia.operations.valves.CacheReadValve class to Jahia versions 4.0 or
4.1, you need to modify the
org.jahia.operations.OperationManager.handleOperations() method (which
functionally overlaps):
if
(jParams.settings().lookupBoolean(SettingsBean.OUTPUT_CACHE_ACTIVATED)) {
/** we only do HTML content caching if it is a core
engine call
* and if the HTTP method is GET. We might extend on
this later
* on but for the sake of simplicity of implementation
we
* restrict it for now. We might be interested in doing
more
* work here in order to cache more often.
*/
if ( ("core".equals(jParams.getEngine())) &&
(jParams.getHttpMethod() == ParamBean.GET_METHOD)
&&
(ParamBean.CACHE_ON.equals(jParams.getCacheStatus()))
)
{
// logger.debug("Requested page is : " +
jParams.getPageID() );
String entryKey = htmlCache.computeEntryKey(
Integer.toString (jParams.getPageID ()),
jParams.getUser().getUsername(),
curLanguageCode,
workflowState,
jParams.getUserAgent ());
CacheEntry cacheEntry =
htmlCache.getCacheEntry(entryKey);
if (cacheEntry != null) {
// logger.debug ("Found HTML page in
cache!!!!!!!!!!!!!!!!!!");
HtmlCacheEntry htmlEntry =
(HtmlCacheEntry)cacheEntry.getObject();
String htmlContent = htmlEntry.getContentBody();
if
(!cacheEntry.getOperationMode().equals(jParams.getOperationMode())) {
logger.debug("Cache entry mode is NOT equal
to current mode, flushing page entry and generating page...");
htmlCache.remove (entryKey);
} else {
if (htmlContent != null) {
logger.debug("Found content in cache,
writing directly bypassing processing...");
HttpServletResponse realResp =
jParams.getRealResponse();
//--------------------- BEGIN: NEW CODE
---------------------------
//return an HTTP 304 Not modified if cache
entry hasn't been changed since last request
HttpServletRequest realReq =
jParams.getRealRequest();
long modSinceHeader =
realReq.getDateHeader("If-Modified-Since");
if (modSinceHeader !=-1) {
Date modSinceHeaderDate = new
Date(modSinceHeader);
Date cacheLastMod =
htmlEntry.getContentTimestamp();
if (
cacheLastMod.before(modSinceHeaderDate)) {
realResp.setStatus(304);
return;
}
}
//--------------------- END: NEW CODE
---------------------------
String contentType =
htmlEntry.getContentType();
if (contentType != null) {
realResp.setContentType(contentType);
logger.debug("Sending content type :
[" + contentType + "]");
}
try {
ServletOutputStream outputStream =
realResp.getOutputStream();
OutputStreamWriter streamWriter =
new
OutputStreamWriter(outputStream);
if (contentType != null) {
int charsetPos =
contentType.toLowerCase().indexOf("charset=");
if (charsetPos != -1) {
String encoding =
contentType.substring(charsetPos + "charset=".length()).toUpperCase();
logger.debug("Using
streamWriter with encoding : " + encoding);
streamWriter = new
OutputStreamWriter
(outputStream, encoding);
}
}
Regards
Marc
_____
From: Marc Cardle [mailto:[email protected]]
Sent: 13 December 2005 11:28
To: [email protected]
Subject: RE: Publication date
Ghislain,
Thanks for your contribution! This code will be particularly useful for
people running Jahia 4.0 and 4.1 (with or without a front-end Apache
server). In Jahia 5.0, we are developing an ESI-enabled webcache server
which supports more advanced caching features. It will replace, and be more
efficient, than a front-end Apache server.
In the meantime, why not go even further with your code and use the
If-Not-Modified HTTP header? If Jahia detects such a header in the request
and the cache entry is old enough, it will quit processing the page and
return an HTTP 304 Not-Modified header (
http://www.checkupdown.com/status/E304.html ).
The best place to add this functionality would be in the
org.jahia.operations.valves.CacheReadValve class. I have written a
(untested) mockup of the necessary changes below which you are welcome to
try. Check for the BEGIN: NEW CODE tagged section. Again, youd need to
recompile the CacheReadValve class and place it in the appropriate package
directory in your webapps/jahia/WEB-INF/classes directory.
public void invoke (Object context, ValveContext valveContext)
throws PipelineException {
ProcessingContext processingContext = (ProcessingContext) context;
// first order of business is to do all cache processing, in order
to
// minimize what we have to do.
if (processingContext.settings().lookupBoolean(SettingsBean.
OUTPUT_CACHE_ACTIVATED)) {
/** we only do HTML content caching if it is a core engine call
* and if the HTTP method is GET. We might extend on this later
* on but for the sake of simplicity of implementation we
* restrict it for now. We might be interested in doing more
* work here in order to cache more often.
*/
HtmlCache htmlCache = null;
try {
// Get the HTML cache instance
htmlCache =
ServicesRegistry.getInstance().getCacheService().getHtmlCacheInstance();
} catch (JahiaInitializationException ex) {
throw new PipelineException(ex);
}
// extract the workflow state out of the parameters bean
int workflowState = processingContext.getEntryLoadRequest().
getWorkflowState();
// Get the language code
String curLanguageCode =
LanguageCodeConverters.localeToLanguageTag(
processingContext.getLocale());
if ( ("core".equals(processingContext.getEngine())) &&
(processingContext.getHttpMethod() ==
ProcessingContext.GET_METHOD) &&
(ProcessingContext.CACHE_ON.equals(processingContext.getCacheStatus()))
) {
// logger.debug("Requested page is : " +
jParams.getObjectKey() );
GroupCacheKey entryKey = htmlCache.computeEntryKey(
Integer.toString(processingContext.getPageID()),
processingContext.getUser().getUsername(),
curLanguageCode,
workflowState,
processingContext.getUserAgent());
CacheEntry cacheEntry = htmlCache.getCacheEntry(entryKey);
if (cacheEntry != null) {
// logger.debug ("Found HTML page in
cache!!!!!!!!!!!!!!!!!!");
HtmlCacheEntry htmlEntry = (HtmlCacheEntry) cacheEntry.
getObject();
String htmlContent = htmlEntry.getContentBody();
if (!cacheEntry.getOperationMode().equals(
processingContext.getOperationMode())) {
logger.debug("Cache entry mode is NOT equal to
current mode, flushing page entry and generating page...");
htmlCache.remove(entryKey);
} else {
if (htmlContent != null) {
logger.debug(
"Found content in cache, writing directly
bypassing processing...");
HttpServletResponse realResp =
((ParamBean)processingContext).
getRealResponse();
String contentType = htmlEntry.getContentType();
//--------------------- BEGIN: NEW CODE
---------------------------
//return an HTTP 304 Not modified if cache entry
hasn't been changed since last request
HttpServletRequest realReq =
((ParamBean)processingContext).
getRealRequest();
long modSinceHeader =
realReq.getDateHeader("If-Modified-Since");
if (modSinceHeader !=-1) {
Date modSinceHeaderDate = new
Date(modSinceHeader);
Date cacheLastMod =
htmlEntry.getContentTimestamp();
if (
cacheLastMod.before(modSinceHeaderDate)) {
realResp.setStatus(304);
return;
}
}
//--------------------- END: NEW CODE
---------------------------
if (contentType != null) {
realResp.setContentType(contentType);
logger.debug("Sending content type : [" +
contentType + "]");
}
try {
ServletOutputStream outputStream = realResp.
getOutputStream();
OutputStreamWriter streamWriter = new
OutputStreamWriter(outputStream);
if (contentType != null) {
int charsetPos =
contentType.toLowerCase().
indexOf("charset=");
if (charsetPos != -1) {
String encoding =
contentType.substring(
charsetPos +
"charset=".length()).
toUpperCase();
logger.debug(
"Using streamWriter with
encoding : " +
encoding);
streamWriter = new
OutputStreamWriter(outputStream,
encoding);
}
}
streamWriter.write(htmlContent, 0,
htmlContent.length());
streamWriter.flush();
} catch (java.io.IOException ioe) {
logger.error(
"Error writing cache output, IOException
generated error",
ioe);
JahiaException outputException = new
JahiaException(
"OperationsManager.handleOperations",
"Error writing cache content to writer",
JahiaException.SECURITY_ERROR,
JahiaException.ERROR_SEVERITY, ioe);
throw new
PipelineException(outputException);
}
return; // exit handling here !
}
}
} else {
logger.debug(
"!!!!!! Could not find HTML page in
cache!!!!!!!!!!!!!!!!!!");
}
}
if (
(ProcessingContext.CACHE_OFFONCE.equals(processingContext.getCacheStatus()))
||
(ProcessingContext.CACHE_BYPASS.equals(processingContext.getCacheStatus()))
||
(ProcessingContext.CACHE_ONLYUPDATE.equals(processingContext.getCacheStatus(
)))
) {
// if we have a mode that is only temporary, all the
// urls will be generated to have the cache active
// by default.
processingContext.setCacheStatus(ProcessingContext.CACHE_ON);
}
} else {
logger.debug("Output cache not activated.");
}
valveContext.invokeNext(context);
}
Kind Regards,
Marc
_____
From: ghislain.cussonneau [mailto:[email protected]]
Sent: 12 December 2005 15:53
To: template_list
Subject: RE: Publication date
Ok !
I've done that and everything goes well ! For your interest, the following
codes are the solution I've use (in order templates adding code / patch on
jahia / apache conf).
I've put the new HtmlCacheEntry in webapps/jahia/WEB-INF/classes directory,
modify the jahia.properties to add the property "readonlyserver" and restart
the server.
TEMPLATES
Here is the code I had in header.inc (after the include of declarations.inc)
:
<%
// Definition des headers en fonction des droits des utilisateurs
// Si on est en anonyme ou que le serveur est utilisé en lecture uniquement
--> utilisation du cache Apache
if (!jData.gui().isLogged() || bIsReadonlyServer)
{
int iCacheMaxExpire = 24*3600; // 24 heures max pour cache Apache
// Get the language code
String curLanguageCode =
LanguageCodeConverters.localeToLanguageTag(jParams.getLocale());
// Extract the workflow state out of the parameters bean
int workflowState = jParams.getEntryLoadRequest().getWorkflowState();
// Get the HTML cache instance
HtmlCache htmlCache = CacheFactory.getHtmlCache();
// Get the CacheEntry
String entryKey =
htmlCache.computeEntryKey(Integer.toString(jParams.getPageID()),
jParams.getUser().getUsername(), curLanguageCode, workflowState,
jParams.getUserAgent());
Date dLastModifiedCacheDate = new Date();
try {
CacheEntry cacheEntry = (CacheEntry)htmlCache.getCacheEntry(entryKey);
HtmlCacheEntry htmlEntry = (HtmlCacheEntry) cacheEntry.getObject();
dLastModifiedCacheDate.setTime(htmlEntry.getContentTimestamp());
} catch(Exception e) {}
Date dExpires = new Date();
dExpires.setTime(dLastModifiedCacheDate.getTime() + iCacheMaxExpire);
logger.debug("Header Expires = " + getDateAsRFC822String(dExpires));
logger.debug("Header Last-Modified = " +
getDateAsRFC822String(dLastModifiedCacheDate));
logger.debug("Header Cache-Control = " + "max-age=" + iCacheMaxExpire + ",
must-revalidate");
response.addHeader("Expires", getDateAsRFC822String(dExpires));
response.addHeader("Last-Modified",
getDateAsRFC822String(dLastModifiedCacheDate));
response.addHeader("Cache-Control", "max-age=" + iCacheMaxExpire + ",
must-revalidate");
}
// Autrement --> pas de cache Apache
else
{
Date dExpiresAbsolute = new Date();
dExpiresAbsolute.setTime(dExpiresAbsolute.getTime() + 24*3600);
logger.debug("Header Cache-Control = no-cache");
logger.debug("Header Pragma = No-Cache");
logger.debug("Header ExpiresAbsolute = " +
getDateAsRFC822String(dExpiresAbsolute));
logger.debug("Header Expires = -1");
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Pragma", "No-Cache");
response.addHeader("ExpiresAbsolute",
getDateAsRFC822String(dExpiresAbsolute));
response.addHeader("Expires", "-1");
}
%>
Here is the code I had in declarations.inc :
private static PropertiesManager properties = new
PropertiesManager(Jahia.getJahiaPropertiesFileName ());
private boolean bIsReadonlyServer =
"true".equals(properties.getProperty("readonlyserver"));
public static SimpleDateFormat RFC822DATEFORMAT = new
SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US);
public static String getDateAsRFC822String(Date date)
{
return RFC822DATEFORMAT.format(date);
}
PATCH JAHIA 4.0.6
Here is my personnal org.jahia.services.cache.HtmlCacheEntry (in red the
code I've had) :
public class HtmlCacheEntry implements Serializable {
/** the HTML body content. */
private String contentBody = "";
/** the HTML content type. */
private String contentType = "";
/** the date of HTMLCacheEntry creation / update **/
private long contentTimestamp = -1;
public HtmlCacheEntry (String contentBody) {
init (contentBody, null, new Date().getTime());
}
public HtmlCacheEntry (String contentBody, String contentType) {
init (contentBody, contentType, new Date().getTime());
}
private void init (String contentBody, String contentType, long
contentTimestamp) {
if (contentBody != null)
this.contentBody = contentBody;
if (contentType != null)
this.contentType = contentType;
this.contentTimestamp = contentTimestamp;
}
final public String getContentType() {
return contentType;
}
final public void setContentType (String contentType) {
this.contentType = contentType;
this.contentTimestamp = new Date().getTime();
}
final public String getContentBody() {
return contentBody;
}
final public void setContentBody (String contentBody) {
this.contentBody = contentBody;
this.contentTimestamp = new Date().getTime();
}
final public long getContentTimestamp() {
return contentTimestamp;
}
}
Then in Apache, I've had a new virtual site declaration for my site
<VirtualHost *:80>
ServerName www.mysite.mydomain.fr
# Logging access
CustomLog "|/apache/2.0.54/bin/rotatelogs
/apache/logs/jahiaconsult_access_mysitekey_log.%Y-%m-%d-%H_%M_%S.log 86400"
common
# Redirections
Redirect /index.html
http://www.mysite.mydomain.fr/jahia/Jahia/site/mysitekey
DocumentRoot /apache/2.0.54/htdocs
RewriteEngine On
RewriteRule /favicon.ico - [F]
RewriteRule (.*)/op(.*)$
http://www.mysite.mydomain.edit.fr/jahia/Jahia/engineName/login/site/mysitek
ey
RewriteRule ^/jahia/administration(.*)$
http://www.mysite.mydomain.edit.fr/jahia/administration
ProxyPass /jahia/Jahia/op !
ProxyPass /jahia/Jahia/site/mysitekey/op !
ProxyPass /jahia/administration !
ProxyPass /jahia http://www.mysite.mydomain.fr:9080/jahia
ProxyPassReverse /jahia http://www.mysite.mydomain.fr:9080/jahia
# Gestion du Cache
CacheRoot "/apache/2.0.54/proxy/www.mysite.mydomain.fr"
CacheSize 50000
CacheEnable disk /
CacheGcInterval 0.25
CacheMaxExpire 180
CacheLastModifiedFactor 0.1
CacheDefaultExpire 0.25
CacheDirLength 2
CacheDirLevels 3
# Expire - by request
ExpiresActive On
ExpiresByType image/gif A86400
ExpiresByType image/png A86400
ExpiresByType image/jpeg A86400
ExpiresByType text/css A86400
</VirtualHost>
Regards for your Help.
Ghislain CUSSONNEAU
DIRR/DPIL/CIS
CAP 44, Rue Marcel Sembat
44000 Nantes
02 51 84 48 80
Accédez au courrier électronique de La Poste : www.laposte.net ;
Jusqu'au 25 décembre, participez au grand jeu du Calendrier de l'Avent et
gagnez tous les jours de nombreux lots, + de 300 cadeaux en jeu !