org.jboss.seam.web
Class ConditionalAbstractResource

java.lang.Object
  extended by org.jboss.seam.web.AbstractResource
      extended by org.jboss.seam.web.ConditionalAbstractResource

public abstract class ConditionalAbstractResource
extends AbstractResource

Subclass this resource if you want to be able to send the right response automatically to any conditional GET or HEAD request. The typically usecase is as follows:

 public class MyResource extends ConditionalAbstractResource {

     public void getResource(final HttpServletRequest request, final HttpServletResponse response) {
         String resourceVersion = ... // Calculate current state as string
         or
         byte[] resourceVersion = ... // Calculate current state as bytes

         String resourcePath = ... // Get the relative (to servlet) path of the requested resource

         if ( !sendConditional(request,
                              response,
                              createdEntityTag(resourceVersion, false),
                              getLastModifiedTimestamp(resourcePath) ) {
 
             // Send the regular resource representation with 200 OK etc.
         }
     }
 }
 

Note that the getLastModifiedTimestamp() method is only supplied for convenience; it may not return what you expect as the "last modification timestamp" of the given resource. In many cases you'd rather calculate that timestamp yourself.

Author:
Christian Bauer

Field Summary
static String HEADER_ETAG
           
static String HEADER_IF_MODIFIED_SINCE
           
static String HEADER_IF_NONE_MATCH
           
static String HEADER_LAST_MODIFIED
           
 
Constructor Summary
ConditionalAbstractResource()
           
 
Method Summary
protected  String createEntityTag(byte[] hashSource, boolean weak)
          Generates a (globally) unique identifier of the current state of the resource.
protected  String createEntityTag(String hashSource, boolean weak)
          Generates a (globally) unique identifier of the current state of the resource.
protected  Long getLastModifiedTimestamp(String resourcePath)
          Tries to get last modification timestamp of the resource by obtaining a URLConnection to the file in the filesystem or JAR.
protected  String hash(byte[] bytes, String algorithm)
           
protected  String hash(String text, String charset, String algorithm)
           
protected  boolean isModifiedSinceConditionValid(Long modifiedSinceHeader, Long lastModified)
           
protected  boolean isNoneMatchConditionValid(String noneMatchHeader, String entityTag)
           
 boolean sendConditional(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, String entityTag, Long lastModified)
          Validates the request headers If-Modified-Since and If-None-Match to determine if a 304 NOT MODIFIED response can be send.
 
Methods inherited from class org.jboss.seam.web.AbstractResource
getResource, getResourcePath, getServletContext, isCompressedMimeType, isGzipEnabled, selectOutputStream, setServletContext
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

HEADER_LAST_MODIFIED

public static final String HEADER_LAST_MODIFIED
See Also:
Constant Field Values

HEADER_IF_MODIFIED_SINCE

public static final String HEADER_IF_MODIFIED_SINCE
See Also:
Constant Field Values

HEADER_ETAG

public static final String HEADER_ETAG
See Also:
Constant Field Values

HEADER_IF_NONE_MATCH

public static final String HEADER_IF_NONE_MATCH
See Also:
Constant Field Values
Constructor Detail

ConditionalAbstractResource

public ConditionalAbstractResource()
Method Detail

sendConditional

public boolean sendConditional(javax.servlet.http.HttpServletRequest request,
                               javax.servlet.http.HttpServletResponse response,
                               String entityTag,
                               Long lastModified)
                        throws IOException
Validates the request headers If-Modified-Since and If-None-Match to determine if a 304 NOT MODIFIED response can be send. If that is the case, this method will automatically send the response and return true. If condition validation fails, it will not change the response and return false.

Note that both entityTag and lastModified arguments can be null. The validation procedure and the outcome depends on what the client requested. If the client requires that both entity tags and modification timestamps be validated, both arguments must be supplied to the method and they must match, for a 304 response to be send.

In addition to responding with 304 NOT MODIFIED when conditions match, this method will also, if arguments are not null, send the right entity tag and last modification timestamps with the response, so that future requests from the client can be made conditional.

Parameters:
request - The usual HttpServletRequest for header retrieval.
response - The usual HttpServletResponse for header manipulation.
entityTag - An entity tag (weak or strong, in doublequotes), typically produced by hashing the content of the resource representation. If null, no entity tag will be send and if validation is requested by the client, no match for a NOT MODIFIED response will be possible.
lastModified - The timestamp in number of milliseconds since unix epoch when the resource was last modified. If null, no last modification timestamp will be send and if validation is requested by the client, no match for a NOT MODIFIED response will be possible.
Returns:
true if a 304 NOT MODIFIED response status has been set, false if requested conditions were invalid given the current state of the resource.
Throws:
IOException - If setting the response status failed.

isNoneMatchConditionValid

protected boolean isNoneMatchConditionValid(String noneMatchHeader,
                                            String entityTag)

isModifiedSinceConditionValid

protected boolean isModifiedSinceConditionValid(Long modifiedSinceHeader,
                                                Long lastModified)

getLastModifiedTimestamp

protected Long getLastModifiedTimestamp(String resourcePath)
Tries to get last modification timestamp of the resource by obtaining a URLConnection to the file in the filesystem or JAR.

Parameters:
resourcePath - The relative (to the servlet) resource path.
Returns:
Either the last modified filestamp or if an error occurs, the JVM system startup timestamp.

createEntityTag

protected String createEntityTag(String hashSource,
                                 boolean weak)
Generates a (globally) unique identifier of the current state of the resource. The string will be hashed with MD5 and the hash result is then formatted before it is returned. If null, a null will be returned.

Parameters:
hashSource - The string source for hashing or the already hashed (strong or weak) entity tag.
weak - Set to true if you want a weak entity tag.
Returns:
The hashed and formatted entity tag result.

createEntityTag

protected String createEntityTag(byte[] hashSource,
                                 boolean weak)
Generates a (globally) unique identifier of the current state of the resource. The bytes will be hashed with MD5 and the hash result is then formatted before it is returned. If null, a null will be returned.

Parameters:
hashSource - The string source for hashing.
weak - Set to true if you want a weak entity tag.
Returns:
The hashed and formatted entity tag result.

hash

protected String hash(String text,
                      String charset,
                      String algorithm)

hash

protected String hash(byte[] bytes,
                      String algorithm)