mcardle 2005/11/24 15:28:34 CET
Modified files:
src/net/sf/j2ep/responsehandlers ResponseHandlerBase.java
src/org/jahia/esi GetThread.java Utils.java
src/org/jahia/esi/cache FragmentCache.java UrlCacheObject.java
Added files:
src/org/jahia/esi/cache CacheAdministrator.java
src/org/jahia/esi/exceptions DetailedServerException.java
Removed files:
src/org/jahia/esi/cache CacheAdminstrator.java
src/org/jahia/esi/exceptions ForbiddenException.java
Log:
* instead of sending custom error message, now forwards Jahia's error message
for HTTP 400, 403, 404, 503 and -newly added- 500.
* now stores in cache responses to "/cache/offonce/" urls to the associated
non-"/cache/offonce/" urls
Revision Changes Path
1.13 +18 -22
esi_server/src/net/sf/j2ep/responsehandlers/ResponseHandlerBase.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/net/sf/j2ep/responsehandlers/ResponseHandlerBase.java.diff?r1=1.12&r2=1.13&f=h
1.10 +68 -56 esi_server/src/org/jahia/esi/GetThread.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/GetThread.java.diff?r1=1.9&r2=1.10&f=h
1.8 +18 -2 esi_server/src/org/jahia/esi/Utils.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/Utils.java.diff?r1=1.7&r2=1.8&f=h
1.1 +161 -0
esi_server/src/org/jahia/esi/cache/CacheAdministrator.java (new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/cache/CacheAdministrator.java?rev=1.1&content-type=text/plain
1.4 +0 -163
esi_server/src/org/jahia/esi/cache/CacheAdminstrator.java (dead)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/cache/CacheAdminstrator.java?rev=1.3&content-type=text/plain
1.7 +28 -29 esi_server/src/org/jahia/esi/cache/FragmentCache.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/cache/FragmentCache.java.diff?r1=1.6&r2=1.7&f=h
1.3 +5 -4 esi_server/src/org/jahia/esi/cache/UrlCacheObject.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/cache/UrlCacheObject.java.diff?r1=1.2&r2=1.3&f=h
1.1 +68 -0
esi_server/src/org/jahia/esi/exceptions/DetailedServerException.java (new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/exceptions/DetailedServerException.java?rev=1.1&content-type=text/plain
1.2 +0 -68
esi_server/src/org/jahia/esi/exceptions/ForbiddenException.java (dead)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/esi_server/src/org/jahia/esi/exceptions/ForbiddenException.java?rev=1.1&content-type=text/plain
Index: ResponseHandlerBase.java
===================================================================
RCS file:
/home/cvs/repository/esi_server/src/net/sf/j2ep/responsehandlers/ResponseHandlerBase.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- ResponseHandlerBase.java 22 Nov 2005 17:23:56 -0000 1.12
+++ ResponseHandlerBase.java 24 Nov 2005 14:28:32 -0000 1.13
@@ -34,7 +34,6 @@
import net.sf.j2ep.model.ResponseHandler;
import net.sf.j2ep.model.AllowedMethodHandler;
-import net.sf.j2ep.model.RequestHandler;
import net.sf.j2ep.requesthandlers.RequestHandlerBase;
import net.sf.j2ep.factories.MethodNotAllowedException;
import net.sf.j2ep.ProxyFilter;
@@ -47,9 +46,9 @@
import org.apache.commons.logging.Log;
import org.jahia.esi.*;
import org.jahia.esi.exceptions.RedirectException;
-import org.jahia.esi.exceptions.ForbiddenException;
+import org.jahia.esi.exceptions.DetailedServerException;
import org.jahia.esi.exceptions.TransferFailedException;
-import org.jahia.esi.cache.CacheAdminstrator;
+import org.jahia.esi.cache.CacheAdministrator;
import org.jahia.esi.cache.CacheObject;
import org.jahia.esi.cache.FragmentCache;
import org.jahia.esi.cache.UrlCacheObject;
@@ -356,8 +355,8 @@
initOrigRequestUrl(clientRequest);
- String cacheKey =
CacheAdminstrator.getInstance().generateEntryKey(clientRequest,
this.getClientRequestURL());
- String clientRequestUrl = this.getClientRequestURL().toString();
+ String cacheKey =
CacheAdministrator.getInstance().generateEntryKey(clientRequest,
this.getClientRequestURL());
+ String clientRequestUrl = this.getClientRequestURL().toString();
//TODO: inefficient: called twice in a row
FragmentCache fragmentCache = FragmentCache.getInstance();
@@ -366,7 +365,6 @@
log.debug(" * BEGIN ---- > Case 1: Passthrough (post etc...) *
url:"+cacheKey);
beginServerRequest();
copyHeadersFromServerResponseToClientResponse(clientResponse);
- //TODO: set cookies here
clientResponse.setStatus(getStatusCode());
if (!methodToServer.getName().equals("HEAD")) //since there is
no content for HEAD requests
@@ -374,7 +372,6 @@
log.debug(" * END ---- > Case 1: Passthrough (post etc...) *
url:"+cacheKey);
}
else {
-
CacheObject cacheObject = null;
boolean freshCopy = false;
boolean redirect = false;
@@ -390,8 +387,8 @@
redirect = true;
cacheKey = e.getRedirectUrlKey(); //get the cache entry
which was originally responsable for generating the Redirection 304 HTTP error
}
- catch (ForbiddenException e) {
- cacheKey = e.getForbiddenUrlKey(); //get the cache entry
which was originally responsable for generating the Forbidden 403 HTTP error
+ catch (DetailedServerException e) {
+ cacheKey = e.getErrorPageUrlKey(); //get the cache entry
which was originally responsable for generating the Forbidden 403 HTTP error
errorStatusCode = e.getStatusCode();
}
catch (TransferFailedException e) {
@@ -448,7 +445,7 @@
public void fetch (HttpServletResponse clientResponse,
HttpServletRequest clientRequest
, String urlKey, String clientRequestUrl)
- throws RedirectException, ForbiddenException,
TransferFailedException {
+ throws RedirectException, DetailedServerException,
TransferFailedException {
//can be called because object is not in cache, or some sub-object
is not in cache
FragmentCache fragmentCache = FragmentCache.getInstance();
@@ -457,8 +454,10 @@
Vector threads = new Vector();
boolean fetchingSkeleton = false;
- if (urlObj==null) {
- //TODO:Need to support all other methods such as POST
!!!!!!!!!!!!!!!!!!!!!!
+ if (urlObj==null //not in cache?
+ || urlObj.getExpirationDateInSecs() < (new Date()).getTime()/1000
//expired? //TODO: when implemented add "+ urlObj.getMaxRemovalDelayInSecs()"
+ ) {
+ //TODO:Need to support all other methods such as POST !
fetchingSkeleton = true;
GetMethod getMethod = Utils.copyMethod(methodToServer);
getMethod.setFollowRedirects( false );
@@ -468,20 +467,17 @@
clientResponse,
clientRequest,
urlKey,
- urlObj, //TODO: will be NULL
+ null, //TODO: will be NULL
clientRequestUrl
);
-
- threads.add(thread);
+ threads.add(thread);
thread.setName("from:RespHdl,["+urlKey.substring(urlKey.length()-15)+"]id:"+thread.getId());
thread.start();
}
else {
String[] refObjs = urlObj.getReferencedObjs();
for (int i=0; i < refObjs.length ; i++) {
-
String refUrlKey = refObjs[i];
-
if (!fragmentCache.contains(refUrlKey)) {
log.debug("Cache MISS on refUrlKey ["+ refUrlKey +"]
referenced by ["+urlKey+"]");
@@ -526,15 +522,15 @@
log.info("throwing RedirectException");
throw new RedirectException("server redirect detected in
thread "+ thread.getName() ,
thread.getRedirectUrlKey() ,
thread.getErrorStatusCode() );
- } else if (thread.isForbiddenDetected()) {
- log.info("throwing ForbiddenException");
- throw new ForbiddenException("server ForbiddenException
detected "+ thread.getName() ,
- thread.getForbiddenUrlKey() ,
thread.getErrorStatusCode() );
+ } else if (thread.isDetailedServerErrorDetected()) {
+ log.info("throwing DetailedServerException");
+ throw new DetailedServerException("server
DetailedServerException detected "+ thread.getName() ,
+ thread.getErrorPageUrlKey() ,
thread.getErrorStatusCode() );
//TODO: check if a TransferFailedException occured (on
all fragments, not just skeleton)
//TODO: and if the error Fragment should be served,
//TODO: or if we should propagate the error (i.e.
setSuccess(false) and setTransferErrorDetected(true)
} else if (thread.isTransferErrorDetected() &&
fetchingSkeleton) {
- log.info("throwing ForbiddenException");
+ log.info("throwing DetailedServerException");
throw new TransferFailedException("server TransferError
detected in thread "+ thread.getName()
, thread.getErrorStatusCode() );
}
Index: GetThread.java
===================================================================
RCS file: /home/cvs/repository/esi_server/src/org/jahia/esi/GetThread.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- GetThread.java 22 Nov 2005 17:23:56 -0000 1.9
+++ GetThread.java 24 Nov 2005 14:28:33 -0000 1.10
@@ -14,7 +14,7 @@
import org.htmlparser.util.ParserException;
import org.htmlparser.nodes.TextNode;
import org.htmlparser.nodes.TagNode;
-import org.jahia.esi.cache.CacheAdminstrator;
+import org.jahia.esi.cache.CacheAdministrator;
import org.jahia.esi.cache.CacheObject;
import org.jahia.esi.cache.FragmentCache;
import org.jahia.esi.cache.UrlCacheObject;
@@ -66,10 +66,10 @@
private int errorStatusCode = -3;//the error code for the failed
transfer or redirection
private boolean redirectDetected = false;
private String redirectUrlKey = null; //holds the UrlKey of the object
which generated the HTTP 304 Redirection error
- private boolean forbiddenDetected = false;
- private String forbiddenUrlKey = null; //holds the UrlKey of the object
which generated the HTTP 403 Forbidden error
+ private boolean detailedServerErrorDetected = false;
+ private String errorPageUrlKey = null; //holds the UrlKey of the object
which generated the HTTP 403 Forbidden error
- long expirationDateInSecs = (new Date()).getTime();
+ long expirationDateInSecs = -2;
long expirationInSecs = EsiConst.DEFAULT_EXPIRATION;
long maxRemovalDelayInSecs = EsiConst.DEFAULT_DELAY;
boolean isContentEsi10 = false; //process standard ESI tags
@@ -135,20 +135,20 @@
this.redirectDetected = redirectDetected;
}
- public boolean isForbiddenDetected() {
- return forbiddenDetected;
+ public boolean isDetailedServerErrorDetected() {
+ return detailedServerErrorDetected;
}
- public void setForbiddenDetected(boolean forbiddenDetected) {
- this.forbiddenDetected = forbiddenDetected;
+ public void setDetailedServerErrorDetected(boolean
detailedServerErrorDetected) {
+ this.detailedServerErrorDetected = detailedServerErrorDetected;
}
- public String getForbiddenUrlKey() {
- return forbiddenUrlKey;
+ public String getErrorPageUrlKey() {
+ return errorPageUrlKey;
}
- public void setForbiddenUrlKey(String forbiddenUrlKey) {
- this.forbiddenUrlKey = forbiddenUrlKey;
+ public void setErrorPageUrlKey(String errorPageUrlKey) {
+ this.errorPageUrlKey = errorPageUrlKey;
}
public String getRedirectUrlKey() {
@@ -190,8 +190,8 @@
try {
bytes = retrieveBytesFromServer();
- ResponseHandlerBase.printRequestHeaders(this.methodToServer,
"from GetThread -"+id+"- for clientRequestUrl:"+clientRequestUrl);
- ResponseHandlerBase.printResponseHeaders(this.methodToServer,
"from GetThread -"+id+"- for clientRequestUrl:"+clientRequestUrl);
+ //ResponseHandlerBase.printRequestHeaders(this.methodToServer,
"from GetThread -"+id+"- for clientRequestUrl:"+clientRequestUrl);
+ //ResponseHandlerBase.printResponseHeaders(this.methodToServer,
"from GetThread -"+id+"- for clientRequestUrl:"+clientRequestUrl);
}
catch (TransferFailedException e) {
log.error(id + " - error: " + e);
@@ -199,7 +199,7 @@
setSuccess(false);
setTransferErrorDetected(true);
setErrorStatusCode(e.getStatusCode());
- String urlKey =
CacheAdminstrator.getInstance().generateEntryKey("GET" , clientRequestUrl );
+ //String urlKey =
CacheAdministrator.getInstance().generateEntryKey("GET" , clientRequestUrl );
StringBuffer errorMsg = new StringBuffer("<b>ESI ERROR: Could
not fetch the object (urlKey:[")
.append(urlKey).append("]) due to error: ");
String status = "undefined";
@@ -222,17 +222,17 @@
setSuccess(false);
setRedirectDetected(true);
setErrorStatusCode(e.getStatusCode());
- String urlKey =
CacheAdminstrator.getInstance().generateEntryKey("GET" , clientRequestUrl );
+ //String urlKey =
CacheAdministrator.getInstance().generateEntryKey("GET" , clientRequestUrl );
setRedirectUrlKey(urlKey);
- fragmentCache.addUnfectched ( urlKey , this.methodToServer ,
"Redirected - this should never appear anywhere to the browser" ,
this.clientRequestUrl);
+ fragmentCache.addUnfectched ( urlKey , this.methodToServer ,
Utils.getErrorPage("HTTP 302 Redirection encountered while requesting this
Fragment") , this.clientRequestUrl);
return;
}
- catch (ForbiddenException e) {
+ catch (DetailedServerException e) {
setSuccess(false);
- setForbiddenDetected(true);
+ setDetailedServerErrorDetected(true);
setErrorStatusCode(e.getStatusCode());
- String urlKey =
CacheAdminstrator.getInstance().generateEntryKey("GET" , clientRequestUrl );
- setForbiddenUrlKey(urlKey);
+ //String urlKey =
CacheAdministrator.getInstance().generateEntryKey("GET" , clientRequestUrl );
+ setErrorPageUrlKey(urlKey);
fragmentCache.addUnfectched ( urlKey , this.methodToServer ,
new String(e.getErrorMsgBytes()) , this.clientRequestUrl);
return;
}
@@ -270,7 +270,7 @@
//contentType.indexOf("text/xml")>-1
) {
- String urlKey =
CacheAdminstrator.getInstance().generateEntryKey("GET" , clientRequestUrl
);//urlToServer);
+ String urlKey =
CacheAdministrator.getInstance().generateEntryKey("GET" , clientRequestUrl
);//urlToServer);
fragmentCache.add ( urlKey , this.methodToServer , bytes ,
this.clientRequestUrl ,
null, null, null ,null); //will set default expirations
for the moment
@@ -317,7 +317,7 @@
String src = esiT.getAttribute("src");
- String tagCacheKey =
CacheAdminstrator.getInstance().generateEntryKey("GET", src);
//TODO:Unhardcode //(((GetMethod)methodToServer).getMETHOD(), src);
+ String tagCacheKey =
CacheAdministrator.getInstance().generateEntryKey("GET", src);
//TODO:Unhardcode //(((GetMethod)methodToServer).getMETHOD(), src);
tagsToReplace.add(esiT);
@@ -346,7 +346,7 @@
null //because this is an internal demand
and there is no clientRequestUrl
);
threads.add(thread);
- thread.setName("from:GetThread,["+
tagCacheKey.substring(tagCacheKey.length()-15)+"]id:"+id);
+ thread.setName("from:GetThread-"+id+",["+
tagCacheKey.substring(tagCacheKey.length()-15)+"]id:"+thread.getId());
thread.start();
}
@@ -360,18 +360,24 @@
try {
thread.join();
//TODO: check if a TransferFailedException occured and
if the error Fragment should be served, or if we should propagate the error
(i.e. setSuccess(false) and setTransferErrorDetected(true)
- if (thread.isRedirectDetected()) {
- log.debug("detected nested HTTP 304 Redirect");
- setSuccess(false); //TODO: not used
- setRedirectDetected(true);
- setErrorStatusCode(thread.getErrorStatusCode());
- //TODO: necessary to save or leave alone?
fragmentCache.addUnfectched ( urlKey , this.methodToServer , "Redirected -
this should never appear anywhere to the browser" , this.clientRequestUrl);
- return;
- } else if (thread.isForbiddenDetected()) {
- log.debug("detected nested HTTP 403 Forbidden");
+
+ //TODO: Currently not forwarding HTTP redirections on
Fragments because
+ //TODO: this redirects the user directly to a fragment
which is not a good behaviour.
+ //TODO: It will therefore instead include the default
error Fragment in place.
+ /*if (thread.isRedirectDetected()) {
+ log.debug("detected nested HTTP 302 Redirect");
+ setSuccess(false); //TODO: not used
+ setRedirectDetected(true);
+ setRedirectUrlKey(thread.getRedirectUrlKey());
+ setErrorStatusCode(thread.getErrorStatusCode());
+ //TODO: necessary to save or leave alone?
fragmentCache.addUnfectched ( urlKey , this.methodToServer , "Redirected -
this should never appear anywhere to the browser" , this.clientRequestUrl);
+ return;
+ } else */
+ if (thread.isDetailedServerErrorDetected()) {
+ log.debug("detected nested HTTP
["+thread.getErrorStatusCode()+"] ");
setSuccess(false); //TODO: not used
- setForbiddenDetected(true);
- setForbiddenUrlKey(thread.getForbiddenUrlKey());
+ setDetailedServerErrorDetected(true);
+ setErrorPageUrlKey(thread.getErrorPageUrlKey());
setErrorStatusCode(thread.getErrorStatusCode());
//TODO: necessary to save or leave alone?
fragmentCache.addUnfectched ( urlKey , this.methodToServer , "Nested Forbidden
- this should never appear anywhere to the browser" , this.clientRequestUrl);
return;
@@ -382,7 +388,6 @@
}
}
-
String[] refObjs = new String[tagsToReplace.size()];
String[] refObjsUrls = new String[tagsToReplace.size()];
int[] referencedObjsStartIndex = new int[tagsToReplace.size()];
@@ -394,13 +399,9 @@
while (tagsEnum.hasMoreElements()) {
EsiIncludeTag esiTag = (EsiIncludeTag)
tagsEnum.nextElement();
- //GetThread thread = (GetThread) threads.elementAt(pos);
-
- //String fetchedContent = thread.getFetchtedContent();
-
String src = esiTag.getAttribute("src");
- String tagCacheKey =
CacheAdminstrator.getInstance().generateEntryKey("GET", src);
//TODO:Unhardcode //(((GetMethod)methodToServer).getMETHOD(), src);
+ String tagCacheKey =
CacheAdministrator.getInstance().generateEntryKey("GET", src);
//TODO:Unhardcode //(((GetMethod)methodToServer).getMETHOD(), src);
//UrlCacheObject tagUrlObj = (UrlCacheObject)
fragmentCache.getHashCache().get(tagCacheKey);
@@ -451,17 +452,28 @@
finalContents.append(e.nextNode ().toHtml());
}
+ String urlToServer = methodToServer.getURI().toString();
+
//Reset expiration to 0 so that it isn't stored in the cache
// due to presence of /cache/ param in url
- if
(Utils.isCacheUrlParamPresent(methodToServer.getURI().toString())) {
+ if (Utils.isCacheUrlParamPresent(urlToServer)) {
+ //rewrite (or add) the associated cache entry which doesn't
+ // contain the "/cache/offonce" parameter in its URL, and
still keep current expirations
+ if (Utils.isCacheOffOnce(urlToServer)) {
+ fragmentCache.add ( Utils.removeCacheOffOnce(urlKey),
methodToServer , finalContents.toString().getBytes()
+ , Utils.removeCacheOffOnce(urlToServer),
+ Utils.removeCacheOffOnce(refObjs),
Utils.removeCacheOffOnce(refObjsUrls),
+ referencedObjsStartIndex ,referencedObjsEndIndex,
+ this.expirationInSecs,
this.expirationDateInSecs, this.maxRemovalDelayInSecs );
+ }
+
log.debug("Setting expiration to 0 for "+urlKey);
- this.expirationInSecs = 0;
- this.expirationDateInSecs = (new Date()).getTime();
- //TODO: this is currently a basic implementation, do more
advanced one which properly supports cache/offonce (see Dev notes)
+ this.expirationInSecs = 4;
+ this.expirationDateInSecs = 4;
}
fragmentCache.add ( urlKey , methodToServer ,
finalContents.toString().getBytes()
- , methodToServer.getURI().toString(),
+ , urlToServer,
refObjs, refObjsUrls,
referencedObjsStartIndex ,referencedObjsEndIndex,
this.expirationInSecs, this.expirationDateInSecs,
this.maxRemovalDelayInSecs );
@@ -478,7 +490,7 @@
private byte[] retrieveBytesFromServer()
- throws TransferFailedException, RedirectException,
ForbiddenException {
+ throws TransferFailedException, RedirectException,
DetailedServerException {
byte[] bytes = null;
int statusCode = SC_NULL;
@@ -568,14 +580,14 @@
"Failed to transfer file: " + urlToServer + "
after " + attempt + " attempts - Return code is: " + statusCode
, HttpStatus.SC_INTERNAL_SERVER_ERROR );
case HttpStatus.SC_FORBIDDEN:
- String errorMsg = id + " - Detected a " + statusCode + "
Forbidden on : " + urlToServer + " Return code is: " + statusCode;
+ case HttpStatus.SC_INTERNAL_SERVER_ERROR :
+ case HttpStatus.SC_NOT_FOUND:
+ case HttpStatus.SC_BAD_REQUEST:
+ String errorMsg = id + " - Detected a " + statusCode + "
Error HTTP code on : " + urlToServer + " Return code is: " + statusCode;
log.info(errorMsg);
- throw new ForbiddenException(errorMsg, bytes,
statusCode);
+ throw new DetailedServerException(errorMsg, bytes,
statusCode);
case HttpStatus.SC_UNAUTHORIZED:
throw new TransferFailedException( "Not authorized.",
statusCode);
- case HttpStatus.SC_NOT_FOUND:
- throw new TransferFailedException( "File: " +
urlToServer + " does not exist"
- , statusCode );
case HttpStatus.SC_MOVED_TEMPORARILY :
case HttpStatus.SC_MOVED_PERMANENTLY :
case HttpStatus.SC_TEMPORARY_REDIRECT :
@@ -696,7 +708,7 @@
ctrlParts[i].indexOf(EsiConst.NO_STORE_REMOTE)>-1 ) {
//TODO: shouldn't have to do assignment since these are the
default values anyway, but do it anyway for good measure
expirationInSecs = 0;
- expirationDateInSecs = (new Date()).getTime();
+ expirationDateInSecs = (new Date()).getTime()/1000;
log.debug(id + " No-Store detected ");
continue;
}
@@ -728,13 +740,13 @@
try {
expirationInSecs = Integer.parseInt( maxAge.substring(0,
plusPos) );
- expirationDateInSecs = (new Date()).getTime() +
expirationInSecs; //new Date( (new Date()).getTime() + expirationInSecs );
+ expirationDateInSecs = ((new Date()).getTime())/1000 +
expirationInSecs; //new Date( (new Date()).getTime() + expirationInSecs );
log.debug(id + " expirationInSecs
["+expirationInSecs+"]");
- log.debug(id + " expirationDateInSecs
["+expirationDateInSecs+"] or ["+new Date(expirationDateInSecs)+"]");
+ log.debug(id + " expirationDateInSecs
["+expirationDateInSecs+"] or ["+new Date(expirationDateInSecs*1000)+"]");
} catch (NumberFormatException ex) {
//maybe it's set to Infinity?
if
(ctrlParts[i].indexOf(EsiConst.INFINITY_EXPIRATION_MARKER) > -1) {
- expirationInSecs = Long.MAX_VALUE; //equivalent to
infinity
+ expirationInSecs = Integer.MAX_VALUE; //equivalent
to infinity
expirationDateInSecs = expirationInSecs; //new
Date(expirationInSecs));
}
else
Index: Utils.java
===================================================================
RCS file: /home/cvs/repository/esi_server/src/org/jahia/esi/Utils.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- Utils.java 22 Nov 2005 17:20:52 -0000 1.7
+++ Utils.java 24 Nov 2005 14:28:33 -0000 1.8
@@ -81,6 +81,22 @@
return false;
}
+ public static String removeCacheOffOnce(String url) {
+ String newUrl = url;
+ if (url.indexOf("/cache/offonce/")==-1) {
+ log.warn("Couldn't find /cache/offonce parameter in the given
url (when it should've) : "+ url);
+ }
+ return newUrl.replaceFirst("/cache/offonce/","/");
+ }
+
+ public static String[] removeCacheOffOnce(String[] urls) {
+ String[] newUrls = new String[urls.length];
+ for (int i=0; i < urls.length; i++) {
+ newUrls[i] =
removeCacheOffOnce(urls[i]);//urls[i].replaceFirst("/cache/offonce/","/");
+ }
+ return newUrls;
+ }
+
public static void copyRequestHeaders(HttpMethod source, HttpMethod
target) throws HttpException {
Header[] requestHeaders = source.getRequestHeaders();
@@ -308,7 +324,7 @@
page.append("</head>\n" );
page.append("\n" );
page.append("<body bgcolor=\"white\">\n" );
- page.append("<font color=\"red\">\n" );
+ page.append("<fieldset style='border-width: 4px; border-color: red;
border: inset'> <font color=\"red\">\n" );
page.append("<h1>Error due to Response from Application Web
Server</h1>\n" );
page.append("<p>No Response from Application Web Server</p>\n" );
page.append("</font>\n" );
@@ -318,7 +334,7 @@
page.append( "There was no response from the application web server
for the page you requested. <br>Please notify the site's webmaster and try your
request again later.\n" );
page.append("<hr>\n" );
page.append("<p><h3>Jahia ESI Cache Server - version
"+jahiaEsiServerBuildNumber+"</h3></p>\n" );
- page.append("\n" );
+ page.append("</fieldset>\n" );
page.append("</body> </html>");
return page.toString();
}
Index: CacheAdministrator.java
====================================================================
package org.jahia.esi.cache;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.httpclient.HttpMethod;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Iterator;
import java.net.URL;
/**
* Created by IntelliJ IDEA.
* User: jahia
* Date: 07-Oct-2005
* Time: 10:19:08
* To change this template use File | Settings | File Templates.
*/
public class CacheAdministrator {
/**
* Constant for Key generation.
*/
private final static short AVERAGE_KEY_LENGTH = 30;
private static final transient Log log =
LogFactory.getLog(CacheAdministrator.class);
private static CacheAdministrator cacheAdminstration;
/**
* Obtain an instance of the CacheAdministrator
*
* @return Returns the CacheAdministrator instance for this context
*/
public static CacheAdministrator getInstance() {
if (cacheAdminstration==null) {
cacheAdminstration = new CacheAdministrator();
if (log.isInfoEnabled()) {
log.info("Created new instance of CacheAdministrator");
}
}
return cacheAdminstration;
}
/**
* Generates a cache entry key.
*/
public String generateEntryKey(HttpServletRequest clientRequest, URL
clientRequestURL) {
/**
* Used for generating cache entry keys.
*/
StringBuffer cBuffer = new StringBuffer(AVERAGE_KEY_LENGTH);
cBuffer.append("_").append(clientRequest.getMethod()).append("_");
//reqUrl.getHOST()
//reqUrl.
// [scheme:][//authority][path][?query][#fragment]
cBuffer.append(clientRequestURL.toString());
return cBuffer.toString();
}
public String generateEntryKey(String method, String Url) {
/**
* Used for generating cache entry keys.
*/
StringBuffer cBuffer = new StringBuffer(AVERAGE_KEY_LENGTH);
cBuffer.append("_").append(method).append("_");
//reqUrl.getHOST()
//reqUrl.
// [scheme:][//authority][path][?query][#fragment]
cBuffer.append(Url);
return cBuffer.toString();
}
//SHOULD REALLY get all what is needed from method object, not from other
params
public String generateEntryKey(HttpMethod method, String methodType,
String Url) {
/**
* Used for generating cache entry keys.
*/
StringBuffer cBuffer = new StringBuffer(AVERAGE_KEY_LENGTH);
cBuffer.append("_").append(methodType).append("_");
//URL reqUrl = requestHandler.getClientRequestURL();
//reqUrl.getHOST()
//reqUrl.
// [scheme:][//authority][path][?query][#fragment]
cBuffer.append(Url);
return cBuffer.toString();
}
/**
* from com.opensymphony.oscache.web.ServletCacheAdministrator
* Creates a string that contains all of the request parameters and
their
* values in a single string. This is very similar to
* <code>HttpServletRequest.getQueryString()</code> except the
parameters are
* sorted by name, and if there is a <code>jsessionid</code> parameter
it is
* filtered out.<p>
* If the request has no parameters, this method returns
<code>null</code>.
*/
protected String getSortedQueryString(HttpServletRequest request) {
Map paramMap = request.getParameterMap();
if (paramMap.isEmpty()) {
return null;
}
Set paramSet = new TreeMap(paramMap).entrySet();
StringBuffer buf = new StringBuffer();
boolean first = true;
for (Iterator it = paramSet.iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String[] values = (String[]) entry.getValue();
for (int i = 0; i < values.length; i++) {
String key = (String) entry.getKey();
if ((key.length() != 10) || !"jsessionid".equals(key)) {
if (first) {
first = false;
} else {
buf.append('&');
}
buf.append(key).append('=').append(values[i]);
}
}
}
// We get a 0 length buffer if the only parameter was a jsessionid
if (buf.length() == 0) {
return null;
} else {
return buf.toString();
}
}
}
Index: FragmentCache.java
===================================================================
RCS file:
/home/cvs/repository/esi_server/src/org/jahia/esi/cache/FragmentCache.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- FragmentCache.java 18 Nov 2005 16:21:23 -0000 1.6
+++ FragmentCache.java 24 Nov 2005 14:28:33 -0000 1.7
@@ -57,7 +57,7 @@
FragmentCache() {
base64 = new Base64();
}
-
+ //TODO: synchronized
public synchronized HashMap getHashCache() {
return hashCache;
}
@@ -65,7 +65,7 @@
public void updateReferenceCount(String[] refObjs) {
if (refObjs!=null)
for (int i=0; i < refObjs.length ; i++) {
- if (contains(refObjs[i])) {
+ if (contains(refObjs[i])) { //TODO: for addUnFectched()
Fragments with expiration=0, then this will return false, need to add a routine
which does not check for expiration
String urlKey = refObjs[i];
UrlCacheObject urlObj = (UrlCacheObject)
hashCache.get(urlKey);
//sanity check, shouldn't have to do it
@@ -74,10 +74,10 @@
log.debug("Increasing reference count for Fragment
at urlKey ["+urlKey +"]. ReferenceCount is now
["+urlObj.getReferenceCount()+"]");
}
else //TODO: check if it can be ZERO
- log.error("IMPOSSIBLE----------------------------
reference count shouldn't be negative or 0 for Fragment at urlKey ["+urlKey
+"]. ReferenceCount is ["+urlObj.getReferenceCount()+"]");
+ log.warn("IMPOSSIBLE----------------------------
reference count shouldn't be negative or 0 for Fragment at urlKey ["+urlKey
+"]. ReferenceCount is ["+urlObj.getReferenceCount()+"]");
}
else
- log.error("IMPOSSIBLE----------------------------
refObjs[i] ["+refObjs[i] +"] is not in cached when it should");
+ log.warn("IMPOSSIBLE----------------------------
refObjs[i] ["+refObjs[i] +"] is not in cached when it should");
}
@@ -97,7 +97,7 @@
referencedObjsStartIndex,
referencedObjsEndIndex,
EsiConst.DEFAULT_EXPIRATION,
- (new Date()).getTime() + EsiConst.DEFAULT_EXPIRATION,
+ (new Date()).getTime()/1000 + EsiConst.DEFAULT_EXPIRATION,
EsiConst.DEFAULT_DELAY );
}
@@ -116,9 +116,9 @@
null,
null,
null,
- 0,
- (new Date()).getTime(),
- 0);
+ -7,
+ -7,
+ -7);
hashCache.put(urlKey,newUrlObj);
log.info("Added Unfectched Error Fragment in cache UrlCacheObject :
" + newUrlObj);
@@ -149,6 +149,7 @@
long maxRemovalDelayInSecs
) {
+ log.debug("Adding ["+urlKey+"] with
expirationDateInSecs:"+expirationDateInSecs);
String byteContentHash = getMD5Hash(byteContent);
UrlCacheObject newUrlObj = null;
@@ -163,7 +164,7 @@
newUrlObj.setReferencedObjsEndIndex(referencedObjsEndIndex);
newUrlObj.setExpirationDelayInSecs(expirationInSecs);
newUrlObj.setExpirationDateInSecs(expirationDateInSecs);
- newUrlObj.setExpirationDateInSecs(maxRemovalDelayInSecs);
+ newUrlObj.setMaxRemovalDelayInSecs(maxRemovalDelayInSecs);
newUrlObj.resetLastUpdateDate();
newUrlObj.initCookies();
updateReferenceCount(refObjs);
@@ -202,25 +203,25 @@
log.debug("Content Cache Hit: recieved content
["+byteContentHash +"] already in cache (for request urlKey ["+urlKey +"])");
}
}
-
- public synchronized boolean contains(String urlKey ) {
+ public boolean contains(String urlKey ) {
UrlCacheObject urlObj = (UrlCacheObject) hashCache.get(urlKey);
if ( urlObj!=null ) {
//Has this fragment expired?
- long now = (new Date()).getTime();
+ long now = (new Date()).getTime()/1000;
if (urlObj.getExpirationDateInSecs() < now ) {
- //might still be valid depending on maxRemovalDelay
- if (urlObj.getExpirationDateInSecs() +
urlObj.getMaxRemovalDelayInSecs() < now ) {
+ /*//might still be valid depending on maxRemovalDelay
+ if (urlObj.getExpirationDateInSecs() +
urlObj.getMaxRemovalDelayInSecs() > now ) {
//the object is stale so fetch it in background but
continue serving this version
//TODO: FETCH THIS OBJECT IN BACKGROUND
+ return true;
}
- else {
+ else {*/
log.debug("Request/Hash Cache MISS: request ["+urlKey
+"] - Object has expired :
expirationDateInSecs["+urlObj.expirationDateInSecs+"]");
return false;
- }
+ //}
}
//sanity check: Shouldn't have to do this check, only for debug
@@ -243,14 +244,14 @@
return true;
}
else
- log.error("IMPOSSIBLE---------------------------- URL object
does not have associated contentCacheObject for urlKey ["+urlKey +"]");
+ log.warn("IMPOSSIBLE---------------------------- URL object
does not have associated contentCacheObject for urlKey ["+urlKey +"]");
} else log.debug("Request/Hash Cache MISS: request ["+urlKey +"]");
EsiStats.getInstance().urlCacheMiss(); //SHOULD REALLY BE CALLED
from code we know for sure is doing a user cache access
return false;
}
- public synchronized CacheObject get(String urlKey) {
+ public CacheObject get(String urlKey) {
if ( hashCache.containsKey(urlKey) ) { //this check shouldn't be
necessary since we should've called contains beforehand
UrlCacheObject urlObj = (UrlCacheObject) hashCache.get(urlKey);
@@ -259,18 +260,18 @@
contentObj.incReadCount();
return new CacheObject(urlObj,contentObj);
} else
- log.error("IMPOSSIBLE---------------------------- did a get() on
an urlKey ["+urlKey +"] which doesn't exist ");
+ log.warn("IMPOSSIBLE---------------------------- did a get() on
an urlKey ["+urlKey +"] which doesn't exist ");
return null;
}
-
+ //TODO: synchronized
public synchronized void remove(String urlKey) {
if ( hashCache.containsKey(urlKey) ) { //this check shouldn't be
necessary since we should've called contains beforehand
UrlCacheObject urlObj = (UrlCacheObject) hashCache.get(urlKey);
remove(urlObj, urlKey);
} else
- log.error("IMPOSSIBLE---------------------------- trying to
remove none existent : "+urlKey );
+ log.warn("IMPOSSIBLE---------------------------- trying to
remove none existent : "+urlKey );
}
-
+ //TODO: synchronized
public synchronized void remove(UrlCacheObject urlObj, String urlKey) {
ContentCacheObject contentObj = (ContentCacheObject)
contentCache.get(urlObj.getContentHash());
@@ -280,7 +281,7 @@
log.debug("Removing unreferenced ["+contentObj+"]");
contentCache.remove(urlObj.getContentHash());
} else if (contentObj.getReferenceCount()<1) {
- log.error("IMPOSSIBLE---------------------------- reference
count is Negative/0 and shouldn't ["+contentObj.getReferenceCount()+"] for " +
urlKey);
+ log.warn("IMPOSSIBLE---------------------------- reference count
is Negative/0 and shouldn't ["+contentObj.getReferenceCount()+"] for " +
urlKey);
}
//Remove all referenced objects (only if referenceCount is 0)
@@ -299,11 +300,11 @@
remove(refUrlObj, refUrlKey);
}
if (refUrlObj.getReferenceCount()<0) { //shouldn't have
to do this
- log.error("IMPOSSIBLE----------------------------
refUrlKey["+refUrlKey+"] has a negative reference count
["+refUrlObj.getReferenceCount()+"]");
+ log.warn("IMPOSSIBLE----------------------------
refUrlKey["+refUrlKey+"] has a negative reference count
["+refUrlObj.getReferenceCount()+"]");
}
}
- else log.error("IMPOSSIBLE----------------------------
urlKey["+urlKey+"] references an object which does exist ["+refUrlKey+"]");
+ else log.warn("IMPOSSIBLE----------------------------
urlKey["+urlKey+"] references an object which does exist ["+refUrlKey+"]");
}
log.debug("Removing ["+urlObj+"]");
@@ -327,12 +328,10 @@
//seems to double size of original content...
return MD5.asHex(content).toString();
}
-
- public synchronized HashMap getContentCache() {
+ public HashMap getContentCache() {
return contentCache;
}
-
- public synchronized HashMap getUrlCache() {
+ public HashMap getUrlCache() {
return hashCache;
}
Index: UrlCacheObject.java
===================================================================
RCS file:
/home/cvs/repository/esi_server/src/org/jahia/esi/cache/UrlCacheObject.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- UrlCacheObject.java 4 Nov 2005 16:50:32 -0000 1.2
+++ UrlCacheObject.java 24 Nov 2005 14:28:33 -0000 1.3
@@ -21,7 +21,7 @@
*/
public class UrlCacheObject {
- private static final transient Log log =
LogFactory.getLog(FragmentCache.class);
+ private static final transient Log log =
LogFactory.getLog(UrlCacheObject.class);
protected String contentHash;
protected Date creationDate;
@@ -37,8 +37,8 @@
protected int[] referencedObjsEndIndex; //end offset position of
referencing Tag in current object
protected String[] referencedObjsUrls; //referenced object's URLs
int referenceCount = 0;
- long expirationDelayInSecs; //expiration delay set in max-age
- long expirationDateInSecs; //actual date/time at which this object will
expire
+ long expirationDelayInSecs = -1; //expiration delay set in max-age
+ long expirationDateInSecs = -1; //actual date/time at which this object
will expire
long maxRemovalDelayInSecs; //optional freshness delay which specifies
an additional period of time the stale object can be served, before it must be
refetched
protected String usernameCookie;
protected Vector cookies = new Vector();
@@ -59,6 +59,7 @@
this.referencedObjsStartIndex = referencedObjsStartIndex;
this.referencedObjsEndIndex = referencedObjsEndIndex;
this.expirationDelayInSecs = expirationInSecs;
+ log.debug("---------------- CREATING expirationDateInSecs from
["+this.expirationDateInSecs+"] to ["+expirationDateInSecs+"] for URL:"+Url);
this.expirationDateInSecs = expirationDateInSecs;
this.maxRemovalDelayInSecs = maxRemovalDelayInSecs;
@@ -136,7 +137,7 @@
}
public void setExpirationDateInSecs(long expirationDateInSecs) {
- this.expirationDateInSecs = expirationDateInSecs;
+ this.expirationDateInSecs = expirationDateInSecs;
}
public String[] getReferencedObjsUrls() {
Index: DetailedServerException.java
====================================================================
package org.jahia.esi.exceptions;
/**
* Created by IntelliJ IDEA.
* User: jahia
* Date: 07-Nov-2005
* Time: 15:20:15
* To change this template use File | Settings | File Templates.
*/
public class DetailedServerException
extends Exception
{
//TODO: implement toString() method
String errorPageUrlKey = null;
byte[] errorMsgBytes = null;
int statusCode = -2;
public DetailedServerException( final String message )
{
super( message );
}
public DetailedServerException( final String message, final Throwable
cause )
{
super( message, cause );
}
public DetailedServerException( final String message , String
errorPageUrlKey, int statusCode )
{
super( message );
this.errorPageUrlKey = errorPageUrlKey;
this.statusCode = statusCode;
}
public DetailedServerException( final String message , byte[]
errorMsgBytes, int statusCode )
{
super( message );
this.errorMsgBytes = errorMsgBytes;
this.statusCode = statusCode;
}
public String getErrorPageUrlKey() {
return errorPageUrlKey;
}
public void setErrorPageUrlKey(String errorPageUrlKey) {
this.errorPageUrlKey = errorPageUrlKey;
}
public byte[] getErrorMsgBytes() {
return errorMsgBytes;
}
public void setErrorMsgBytes(byte[] errorMsgBytes) {
this.errorMsgBytes = errorMsgBytes;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
}