--- /dev/null
+package de.halbekunst.juplo.cachecontrol;
+
+
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ * Wenn ein Handler (i.A. eine Impelementierung von {@Controller}),
+ * dieses Interface implementiert, dann schreibt
+ * {@link CachingInterceptor} HTTP/1.1-Caching-Header nach
+ * {@linkplain http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html RFC 2616}
+ * in den Response.
+ *
+ * @see CachingInterceptor
+ * @author kai
+ */
+public interface Cacheable {
+ public boolean accepts(HttpServletRequest request);
+
+ /**
+ * Wenn die Methode <code>false</code> zurückliefert, werden von
+ * {@link CachingDispatcherServlet#isRessourceModified(HttpServletRequest, HttpServletResponse, Cacheable)}
+ * keinerlei HTTP/1.1-Cache-Header in den Response eingebaut.
+ * <p>
+ * Über diese Methode kann z.B. gesteuert werden, dass für eine bestimmte
+ * HTTP-Methode (z.B. POST) keine Cache-Header generiert werden.
+ *
+ * @see CachingDispatcherServlet
+ * @param request
+ * Der aktuelle HTTP-Request
+ * @return <code>true</code>, wenn Caching-Header in den Response geschrieben
+ * werden sollen, sonst <code>false</code>.
+ * @throws IllegalArgumentException
+ * Wenn zu dem Request keine Ressource existiert.
+ */
+ public boolean isGenerateCacheHeaders(HttpServletRequest request) throws IllegalArgumentException;
+
+ /**
+ * Diese Methode ermöglicht eine einfache, zentrale Steuerung des
+ * Caching-Verhaltens.
+ * <ul>
+ * <li>Wenn die Methode den Wert <code>0</code> (oder einen anderen Wert
+ * kleiner <code>1</code>) zurückliefert, werden Cache-Header erzeugt, die das
+ * Cachen der Antwort für HTTP/1.0 und HTTP/1.1 vollständig untersagen,</li>
+ * <li>Wenn die Methode einen Wert größer <code>0</code> zurückliefert, wird
+ * ein für HTTP/1.0-Clients ein <code>Expires</code>-Header generiert und für
+ * HTTP/1.1-Clients ein <code>Cache-Control</code>-Header mit einem
+ * entsprechenden <code>max-age</code>-Eintrag. Dies reicht in Kombination mit
+ * einem sinnvollen Rückgabewert der Methode
+ * {@link #getLastModified(javax.servlet.http.HttpServletRequest)} vollständig
+ * für ein einfaches Caching aus.</li>
+ * </ul>
+ * <p>
+ * <strong>Zu beachten:</strong> Wenn die Methode
+ * {@link #getCacheControl(javax.servlet.http.HttpServletRequest)} weitere
+ * Schlüssel-Wert-Paare für den <code>Cache-Control</code>-Header liefert,
+ * werden diese ergänzt. Wenn in der Rückgabe ein Wert für
+ * <code>max-age</code> enthalten ist, wir er allerdings von dem durch diese
+ * Methode vorgegebenen Wert überschrieben!
+ *
+ * @see #getLastModified(javax.servlet.http.HttpServletRequest)
+ * @see #getCacheControl(javax.servlet.http.HttpServletRequest)
+ * @param request
+ * Der aktuelle HTTP-Request
+ * @return Die gewünschte Cache-Zeit in Sekunden, oder <code>0</code>, wenn
+ * Caching aktiv unterbunden werden soll bzw. einen Wert kleiner
+ * <code>0</code>, wenn kein <code>Expires</code>-Header generiert
+ * werden soll.
+ * @throws IllegalArgumentException
+ * Wenn zu dem Request keine Ressource existiert.
+ */
+ public int getCacheSeconds(HttpServletRequest request) throws IllegalArgumentException;
+
+ /**
+ * Zeitpunkt, zu dem die Ressource zuletzt verändert wurde. Erwartet wird eine
+ * Zeitangabe in Millisekunden seit dem Unix-0-Zeitpunkt, wie sie von
+ * {@link HttpServletResponse#setDateHeader(String, long)} erwartet wird.
+ * <p>
+ * <strong>Zu beachten:</strong>
+ * <ul>
+ * <li>Diese Methode wird nicht aufgerufen, wenn
+ * {@link #getCacheSeconds(javax.servlet.http.HttpServletRequest)}
+ * <code>0</code> liefert.</li>
+ * </ul>
+ *
+ * @see #getCacheSeconds(javax.servlet.http.HttpServletRequest)
+ * @param request
+ * Der aktuelle HTTP-Request
+ * @return Zeitstempel, zu dem die Ressource zuletzt modifiziert wurde.
+ * @throws IllegalArgumentException
+ * Wenn zu dem Request keine Ressource existiert.
+ */
+ public long getLastModified(HttpServletRequest request) throws IllegalArgumentException;
+
+ /**
+ * Frei wählbares ETag nach {@linkplain http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19 RFC 2616,
+ * Abschnitt 14.19 ETag}. Der ETag wird unverändert übernommen und muss den
+ * Bedingungen aus dem RFC 2616 entsprechen. Beispiele für erlaubte Werte:
+ * <ul>
+ * <li><code>"24afh2w3848adf"</code>
+ * <li><code>W/"839482"</code>
+ * <li><code>""</code>
+ * </ul>
+ * <strong>Merke:</strong> Der wert ist immer in doppelte Anführungszeichen
+ * einzuschließen!
+ * <p>
+ * <strong>Zu beachten:</strong>
+ * <ul>
+ * <li>Diese Methode wird nicht aufgerufen, wenn
+ * {@link #getCacheSeconds(javax.servlet.http.HttpServletRequest)}
+ * <code>0</code> liefert.</li>
+ * </ul>
+ *
+ * @see #getCacheSeconds(javax.servlet.http.HttpServletRequest)
+ * @param request
+ * Der aktuelle HTTP-Request
+ * @return Das zu verwendende ETag, oder <code>null</code>, wenn der Header
+ * nicht generiert werden soll.
+ * @throws IllegalArgumentException
+ * Wenn zu dem Request keine Ressource existiert.
+ */
+ public String getETag(HttpServletRequest request) throws IllegalArgumentException;
+
+ /**
+ * Diese Methode liefert eine Map mit Schlüssel-Wert-Paaren für den
+ * HTTP/1.1-Header <code>Cache-Control</code> (s. {@plainlink
+ * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3 RFC2616,
+ * Abschnitt 14.9.3}).
+ * <p>
+ * <strong>Zu beachten:</strong>
+ * <ul>
+ * <li>Die Methode darf nie <code>null</code> zurückliefern!</li>
+ * <li>Ein Wert für den Schlüssel <code>max-age</code> wird überschrieben,
+ * wenn die Methode
+ * {@link #getCacheSeconds(javax.servlet.http.HttpServletRequest)} einen Wert
+ * größer <code>0</code> zurückliefert.</li>
+ * <li>Diese Methode wird nicht aufgerufen, wenn
+ * {@link #getCacheSeconds(javax.servlet.http.HttpServletRequest)}
+ * <code>0</code> liefert.</li>
+ * </ul>
+ *
+ * @see #getCacheSeconds(javax.servlet.http.HttpServletRequest)
+ * @param request
+ * Der aktuelle HTTP-Request
+ * @return Eine <code>Map</code> mit den Schlüssel-Wert-Paaren für den
+ * <code>Cache-Control</code>-Header.
+ * @throws IllegalArgumentException
+ * Wenn zu dem Request keine Ressource existiert.
+ */
+ public Map<String, String> getCacheControl(HttpServletRequest request) throws IllegalArgumentException;
+}