--- /dev/null
+// HttpCacheControl.java\r
+// $Id: HttpCacheControl.java,v 1.1 2010/06/15 12:19:52 smhuang Exp $\r
+// (c) COPYRIGHT MIT and INRIA, 1996.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+\r
+package org.w3c.www.http;\r
+\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * The parsed cache-control directive of HTTP/1.1\r
+ * This object gives access to the parsed value of the cache-control\r
+ * directive of HTTP/1.1, as defined in section 14.9 of the specification.\r
+ */\r
+\r
+public class HttpCacheControl extends BasicValue {\r
+ private static final String EMPTY_LIST[] = { };\r
+\r
+ private String nocache[] = null ;\r
+ private boolean nostore = false;\r
+ private int maxage = -1;\r
+ private int maxstale = -1;\r
+ private int minfresh = -1;\r
+ private boolean onlyifcached = false;\r
+ private boolean pub = false ;\r
+ private String priv[] = null ;\r
+ private boolean notransform = false;\r
+ private boolean mustrevalidate = false;\r
+ private boolean proxyrevalidate = false;\r
+ private int s_maxage = -1;\r
+ private Vector extensions = null;\r
+\r
+ private static final int NOCACHE = (1<<0);\r
+ private static final int NOSTORE = (1<<1);\r
+ private static final int MAXAGE = (1<<2);\r
+ private static final int MINVERS = (1<<3);\r
+ private static final int ONLYIFCACHED = (1<<4);\r
+ private static final int PUB = (1<<5);\r
+ private static final int PRIV = (1<<6);\r
+ private static final int NOTRANSFORM = (1<<7);\r
+ private static final int MUSTREVALIDATE = (1<<8);\r
+ private static final int PROXYREVALIDATE = (1<<9);\r
+ private static final int MAXSTALE = (1<<10);\r
+ private static final int MINFRESH = (1<<11);\r
+ private static final int S_MAXAGE = (1<<12);\r
+\r
+ private int defined = 0 ;\r
+\r
+ /**\r
+ * Check if the given field has been explictly set.\r
+ * @param id The field identifier.\r
+ * @return A boolean.\r
+ */\r
+\r
+ private final boolean checkDirective(int id) {\r
+ return (defined & id) != 0;\r
+ }\r
+\r
+ /**\r
+ * Mark the given field as being set.\r
+ * @param id The field identifier.\r
+ */\r
+\r
+ private final void setDirective(int id) {\r
+ defined |= id;\r
+ }\r
+\r
+ /**\r
+ * Mark the given field as being unset.\r
+ * @param id The field identifier.\r
+ */\r
+\r
+ private final void unsetDirective(int id) {\r
+ defined &= (~id);\r
+ }\r
+\r
+ /**\r
+ * Recompute the byte value for this header.\r
+ */\r
+\r
+ protected void updateByteValue() {\r
+ // Dump the value, using my own version of the StringBuffer:\r
+ HttpBuffer buf = new HttpBuffer();\r
+ boolean cnt = false;\r
+ if (checkDirective(NOCACHE)) {\r
+ if ( nocache != null )\r
+ buf.appendQuoted("no-cache", (byte) '=', nocache);\r
+ else\r
+ buf.append("no-cache");\r
+ cnt = true;\r
+ }\r
+ if(checkDirective(NOSTORE) && nostore) {\r
+ buf.append("no-store");\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(MAXAGE) && (maxage >= 0)) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("max-age", (byte) '=', maxage);\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(ONLYIFCACHED) && onlyifcached) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("only-if-cached");\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(PUB) && pub) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("public");\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(PRIV) && (priv != null)) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.appendQuoted("private", (byte) '=', priv);\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(NOTRANSFORM) && notransform) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("no-transform");\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(MUSTREVALIDATE) && mustrevalidate) { \r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("must-revalidate");\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(PROXYREVALIDATE) && proxyrevalidate) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("proxy-revalidate");\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(MAXSTALE) && (maxstale >= 0)) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("max-stale", (byte) '=', maxstale);\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(MINFRESH) && (minfresh >= 0)) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("min-fresh", (byte) '=', minfresh);\r
+ cnt = true;\r
+ }\r
+ if (checkDirective(S_MAXAGE) && (s_maxage >= 0)) {\r
+ if ( cnt )\r
+ buf.append(',');\r
+ buf.append("s_maxage", (byte) '=', s_maxage);\r
+ cnt = true;\r
+ }\r
+ if (extensions != null) {\r
+ Enumeration e = extensions.elements();\r
+ while (e.hasMoreElements()) {\r
+ if (cnt) {\r
+ buf.append(',');\r
+ cnt = true;\r
+ }\r
+ buf.append((String) e.nextElement());\r
+ }\r
+ }\r
+ // Keep track of the string, for potential reuse:\r
+ raw = buf.getByteCopy();\r
+ roff = 0;\r
+ rlen = raw.length;\r
+ }\r
+\r
+ // Efficient regular expression is what I would do in C\r
+\r
+ private static byte bnocache[] = { \r
+ (byte) 'n', (byte) 'o', (byte) '-', (byte) 'c', \r
+ (byte) 'a', (byte) 'c', (byte) 'h', (byte) 'e' \r
+ } ;\r
+ private static byte bnostore[] = {\r
+ (byte) 'n', (byte) 'o', (byte) '-', (byte) 's',\r
+ (byte) 't', (byte) 'o', (byte) 'r', (byte) 'e'\r
+ };\r
+ private static final byte bmaxage[] = {\r
+ (byte) 'm', (byte) 'a', (byte) 'x', (byte) '-',\r
+ (byte) 'a', (byte) 'g', (byte) 'e'\r
+ };\r
+ private static final byte bs_maxage[] = {\r
+ (byte) 's', (byte) '-', (byte) 'm', (byte) 'a',\r
+ (byte) 'x', (byte) 'a', (byte) 'g', (byte) 'e'\r
+ };\r
+ private static final byte bmaxstale[] = {\r
+ (byte) 'm', (byte) 'a', (byte) 'x', (byte) '-', \r
+ (byte) 's', (byte) 't', (byte) 'a', (byte) 'l',\r
+ (byte) 'e'\r
+ };\r
+ private static final byte bminfresh[] = {\r
+ (byte) 'm', (byte) 'i', (byte) 'n', (byte) '-',\r
+ (byte) 'f', (byte) 'r', (byte) 'e', (byte) 's',\r
+ (byte) 'h'\r
+ };\r
+ private static final byte bonlyifcached[] = {\r
+ (byte) 'o', (byte) 'n', (byte) 'l', (byte) 'y', \r
+ (byte) '-', (byte) 'i', (byte) 'f', (byte) '-', \r
+ (byte) 'c', (byte) 'a', (byte) 'c', (byte) 'h', \r
+ (byte) 'e', (byte) 'd'\r
+ };\r
+ private static final byte bpublic[] = {\r
+ (byte) 'p', (byte) 'u', (byte) 'b', (byte) 'l',\r
+ (byte) 'i', (byte) 'c', \r
+ };\r
+ private static final byte bprivate[] = {\r
+ (byte) 'p', (byte) 'r', (byte) 'i', (byte) 'v',\r
+ (byte) 'a', (byte) 't', (byte) 'e'\r
+ };\r
+ private static final byte bnotransform[] = {\r
+ (byte) 'n', (byte) 'o', (byte) '-', (byte) 't',\r
+ (byte) 'r', (byte) 'a', (byte) 'n', (byte) 's',\r
+ (byte) 'f', (byte) 'o', (byte) 'r', (byte) 'm' \r
+ };\r
+ private static final byte bmustrevalidate[] = {\r
+ (byte) 'm', (byte) 'u', (byte) 's', (byte) 't',\r
+ (byte) '-', (byte) 'r', (byte) 'e', (byte) 'v', \r
+ (byte) 'a', (byte) 'l', (byte) 'i', (byte) 'd', \r
+ (byte) 'a', (byte) 't', (byte) 'e'\r
+ };\r
+ private static final byte bproxyrevalidate[] = {\r
+ (byte) 'p', (byte) 'r', (byte) 'o', (byte) 'x',\r
+ (byte) 'y', (byte) '-', (byte) 'r', (byte) 'e',\r
+ (byte) 'v', (byte) 'a', (byte) 'l', (byte) 'i', \r
+ (byte) 'd', (byte) 'a', (byte) 't', (byte) 'e'\r
+ };\r
+\r
+ // Parse a valued-directive\r
+ private final void parseDirective(int ds, int de, ParseState pval)\r
+ throws HttpParserException\r
+ {\r
+ if (HttpParser.compare(raw, ds, de, bmaxage) == 0) {\r
+ pval.ioff = pval.start;\r
+ pval.bufend = pval.end;\r
+ maxage = HttpParser.parseInt(raw, pval);\r
+ setDirective(MAXAGE);\r
+ } else if (HttpParser.compare(raw, ds, de, bmaxstale) == 0) {\r
+ pval.ioff = pval.start;\r
+ pval.bufend = pval.end;\r
+ maxstale = HttpParser.parseInt(raw, pval);\r
+ setDirective(MAXSTALE);\r
+ } else if (HttpParser.compare(raw, ds, de, bminfresh) == 0) {\r
+ pval.ioff = pval.start;\r
+ pval.bufend = pval.end;\r
+ minfresh = HttpParser.parseInt(raw, pval);\r
+ setDirective(MINFRESH);\r
+ } else if (HttpParser.compare(raw, ds, de, bs_maxage) == 0) {\r
+ pval.ioff = pval.start;\r
+ pval.bufend = pval.end;\r
+ s_maxage = HttpParser.parseInt(raw, pval);\r
+ setDirective(S_MAXAGE);\r
+ } else if (HttpParser.compare(raw, ds, de, bnocache) == 0) {\r
+ Vector fields = new Vector(8);\r
+ ParseState sp = new ParseState();\r
+ sp.ioff = pval.start;\r
+ sp.bufend = pval.end;\r
+ HttpParser.unquote(raw, sp);\r
+ while (HttpParser.nextItem(raw, sp) >= 0) {\r
+ fields.addElement(new String(raw,0,sp.start,sp.end-sp.start));\r
+ sp.prepare();\r
+ }\r
+ if (nocache == null) {\r
+ nocache = new String[fields.size()];\r
+ fields.copyInto(nocache);\r
+ } else {\r
+ int num = fields.size();\r
+ String t_nocache[] = new String[nocache.length+num];\r
+ System.arraycopy(nocache, 0, t_nocache, 0, nocache.length);\r
+ for (int i=0; i< num; i++) {\r
+ t_nocache[nocache.length+i] = (String) fields.elementAt(i);\r
+ }\r
+ nocache = t_nocache;\r
+ }\r
+ setDirective(NOCACHE);\r
+ } else if (HttpParser.compare(raw, ds, de, bprivate) == 0) {\r
+ Vector fields = new Vector(8);\r
+ ParseState sp = new ParseState();\r
+ sp.ioff = pval.start;\r
+ sp.bufend = pval.end;\r
+ HttpParser.unquote(raw, sp);\r
+ while (HttpParser.nextItem(raw, sp) >= 0) {\r
+ fields.addElement(new String(raw,0,sp.start,sp.end-sp.start));\r
+ sp.prepare();\r
+ }\r
+ if (priv == null) {\r
+ priv = new String[fields.size()];\r
+ fields.copyInto(priv);\r
+ } else {\r
+ int num = fields.size();\r
+ String t_priv[] = new String[priv.length+num];\r
+ System.arraycopy(priv, 0, t_priv, 0, priv.length);\r
+ for (int i=0; i< num; i++) {\r
+ t_priv[priv.length+i] = (String) fields.elementAt(i);\r
+ }\r
+ priv = t_priv;\r
+ }\r
+ setDirective(PRIV);\r
+ } else {\r
+ if (extensions == null) {\r
+ extensions = new Vector(4);\r
+ extensions.add(new String(raw,0,ds,de-ds));\r
+ }\r
+// error("Unknown directive "+new String(raw, 0, ds, de-ds));\r
+ }\r
+ }\r
+\r
+ // Parse a boolean directive\r
+ private final void parseDirective(int ds, int de)\r
+ throws HttpParserException\r
+ {\r
+ if (HttpParser.compare(raw, ds, de, bnocache) == 0) {\r
+ setDirective(NOCACHE);\r
+ nocache = EMPTY_LIST;\r
+ } else if (HttpParser.compare(raw, ds, de, bnostore) == 0) {\r
+ setDirective(NOSTORE);\r
+ nostore = true;\r
+ } else if (HttpParser.compare(raw, ds, de, bonlyifcached) == 0) {\r
+ setDirective(ONLYIFCACHED);\r
+ onlyifcached = true;\r
+ } else if (HttpParser.compare(raw, ds, de, bpublic) == 0) {\r
+ setDirective(PUB);\r
+ pub = true;\r
+ } else if (HttpParser.compare(raw, ds, de, bprivate) == 0) {\r
+ setDirective(PRIV);\r
+ priv = EMPTY_LIST;\r
+ } else if (HttpParser.compare(raw, ds, de, bnotransform) == 0) {\r
+ setDirective(NOTRANSFORM);\r
+ notransform = true;\r
+ } else if (HttpParser.compare(raw, ds, de, bmustrevalidate) == 0) {\r
+ setDirective(MUSTREVALIDATE);\r
+ mustrevalidate = true;\r
+ } else if (HttpParser.compare(raw, ds, de, bproxyrevalidate) == 0) {\r
+ setDirective(PROXYREVALIDATE);\r
+ proxyrevalidate = true;\r
+ } else {\r
+ if (extensions == null) {\r
+ extensions = new Vector(4);\r
+ extensions.add(new String(raw,0,ds,de-ds));\r
+ }\r
+// error("Unknown or invalid directive: "+new String(raw,0,ds,de));\r
+ }\r
+ }\r
+\r
+ /**\r
+ * parse.\r
+ * @exception HttpParserException if parsing failed.\r
+ */\r
+ protected void parse() \r
+ throws HttpParserException\r
+ {\r
+ // Parse the raw value, this is the right time to do it:\r
+ ParseState ls = new ParseState(0);\r
+ ls.ioff = 0;\r
+ ls.bufend = raw.length;\r
+ ls.separator = (byte) ',';\r
+ ls.spaceIsSep = false; // gift for broken implementations\r
+ ParseState ld = new ParseState(0);\r
+ ld.separator = (byte) '=';\r
+ ld.spaceIsSep = false; // gift for broken implementations\r
+// HttpParser.unquote(raw, ls); \r
+ while (HttpParser.nextItem(raw, ls) >= 0) {\r
+ ld.bufend = ls.end;\r
+ ld.ioff = ls.start;\r
+ if ( HttpParser.nextItem(raw, ld) >= 0 ) {\r
+ int dstart = ld.start;\r
+ int dend = ld.end;\r
+ ld.prepare();\r
+ if ( HttpParser.nextItem(raw, ld) >= 0 )\r
+ parseDirective(dstart, dend, ld);\r
+ else\r
+ parseDirective(dstart, dend);\r
+ } else {\r
+ parseDirective(ls.start, ls.end);\r
+ }\r
+ ls.prepare();\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * HeaderValue implementation - Get this header value.\r
+ * @return Itself !\r
+ */\r
+\r
+ public Object getValue() {\r
+ validate();\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * Get and test the no-cache directive setting.\r
+ * @return A field-list as an array of String, or <strong>null</strong>\r
+ * if the directive is undefined.\r
+ */\r
+\r
+ public String[] getNoCache() {\r
+ validate();\r
+ return checkDirective(NOCACHE) ? nocache : null;\r
+ }\r
+\r
+ /**\r
+ * Set the no cache directive to the given list of fields.\r
+ * @param fields The fields to set in the no-cache directive, encoded\r
+ * as a String array (whose length can be <strong>0</strong>), or\r
+ * <strong>null</strong> to reset the value.\r
+ */\r
+\r
+ public void setNoCache(String fields[]) {\r
+ validate();\r
+ if ( fields == null ) {\r
+ if ( checkDirective(NOCACHE) )\r
+ invalidateByteValue();\r
+ unsetDirective(NOCACHE) ;\r
+ } else {\r
+ setDirective(NOCACHE);\r
+ nocache = fields;\r
+ invalidateByteValue();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set the <code>no-cache</code> directive globally.\r
+ */\r
+\r
+ public void setNoCache() {\r
+ validate();\r
+ setDirective(NOCACHE);\r
+ invalidateByteValue();\r
+ }\r
+\r
+ /**\r
+ * Add the given header name to the <code>no-cache</code> directive.\r
+ * @param name The header name to add.\r
+ */\r
+\r
+ public void addNoCache(String name) {\r
+ validate();\r
+ // If no-cache is set globally, then skip...\r
+ if ( checkDirective(NOCACHE) && (nocache.length == 0))\r
+ return;\r
+ // Add or test for presence\r
+ if ( nocache != null ) {\r
+ // Check for that header name presence:\r
+ for (int i = 0 ; i < nocache.length ; i++)\r
+ if (nocache[i].equalsIgnoreCase(name))\r
+ return;\r
+ invalidateByteValue();\r
+ String newcache[] = new String[nocache.length+1];\r
+ System.arraycopy(nocache, 0, newcache, 0, nocache.length);\r
+ newcache[nocache.length] = name;\r
+ nocache = newcache;\r
+ } else {\r
+ invalidateByteValue();\r
+ nocache = new String[1];\r
+ nocache[0] = name;\r
+ }\r
+ setDirective(NOCACHE);\r
+ }\r
+\r
+ /**\r
+ * Unset the <code>no-cache</code> directive.\r
+ */\r
+\r
+ public void unsetNoCache() {\r
+ validate();\r
+ if ( checkDirective(NOCACHE) ) {\r
+ invalidateByteValue();\r
+ unsetDirective(NOCACHE);\r
+ nocache = null;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Is the no-store flag set ?\r
+ * @return A boolean.\r
+ */\r
+\r
+ public boolean checkNoStore() {\r
+ validate();\r
+ return checkDirective(NOSTORE) ? nostore : false;\r
+ }\r
+\r
+ /**\r
+ * Set the <code>no-store</code> flag.\r
+ * @param onoff The value for the no-store directive.\r
+ */\r
+\r
+ public void setNoStore(boolean onoff) {\r
+ validate();\r
+ if ( onoff == false ) {\r
+ if ( nostore ) {\r
+ invalidateByteValue();\r
+ nostore = false;\r
+ }\r
+ unsetDirective(NOSTORE);\r
+ } else if ( ! nostore ) {\r
+ invalidateByteValue();\r
+ setDirective(NOSTORE);\r
+ nostore = true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the max-age value defined by this cache control policy.\r
+ * @return The max-age value, or <strong>-1</strong> if undefined.\r
+ */\r
+\r
+ public final int getMaxAge() {\r
+ validate();\r
+ return checkDirective(MAXAGE) ? maxage : -1;\r
+ }\r
+\r
+ /**\r
+ * Set the max-age directive for this cache control.\r
+ * @param age The max allowed age for the cache control policy, or\r
+ * <strong>-1</strong> to reset value.\r
+ */\r
+\r
+ public void setMaxAge(int age) {\r
+ validate();\r
+ if ( age == -1 ) {\r
+ if ( checkDirective(MAXAGE) )\r
+ invalidateByteValue();\r
+ maxage = -1;\r
+ unsetDirective(MAXAGE);\r
+ } else {\r
+ if ((age != maxage) || ! checkDirective(MAXAGE))\r
+ invalidateByteValue();\r
+ setDirective(MAXAGE);\r
+ maxage = age;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the s-maxage value defined by this cache control policy.\r
+ * @return The s-maxage value, or <strong>-1</strong> if undefined.\r
+ */\r
+ public final int getSMaxAge() {\r
+ validate();\r
+ return checkDirective(S_MAXAGE) ? s_maxage : -1;\r
+ }\r
+\r
+ /**\r
+ * Set the s_maxage directive for this cache control.\r
+ * @param age The max allowed age for the cache control policy, or\r
+ * <strong>-1</strong> to reset value.\r
+ */\r
+ public void setSMaxAge(int age) {\r
+ validate();\r
+ if ( age == -1 ) {\r
+ if ( checkDirective(S_MAXAGE) )\r
+ invalidateByteValue();\r
+ s_maxage = -1;\r
+ unsetDirective(S_MAXAGE);\r
+ } else {\r
+ if ((age != s_maxage) || ! checkDirective(S_MAXAGE))\r
+ invalidateByteValue();\r
+ setDirective(S_MAXAGE);\r
+ s_maxage = age;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the max-stale value defined by this control object.\r
+ * @return The max-stale value, or <strong>-1</strong> if undefined.\r
+ */\r
+\r
+ public int getMaxStale() {\r
+ validate();\r
+ return checkDirective(MAXSTALE) ? maxstale : -1;\r
+ }\r
+\r
+ /**\r
+ * Set the max-stale directive value.\r
+ * @param stale The max-stale value, or <strong>-1</strong> to reset value.\r
+ */\r
+\r
+ public void setMaxStale(int stale) {\r
+ validate();\r
+ if ( stale == -1 ) {\r
+ if ( checkDirective(MAXSTALE) )\r
+ invalidateByteValue();\r
+ maxstale = -1;\r
+ unsetDirective(MAXSTALE);\r
+ } else {\r
+ if ((stale != maxstale) || ! checkDirective(MAXSTALE))\r
+ invalidateByteValue();\r
+ setDirective(MAXSTALE);\r
+ maxstale = stale;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the min-fresh directive value.\r
+ * @param def The default value to reurn if undefined.\r
+ */\r
+\r
+ public int getMinFresh() {\r
+ validate();\r
+ return checkDirective(MINFRESH) ? minfresh : -1;\r
+ }\r
+\r
+ /**\r
+ * Set the minfresh directive value.\r
+ * @param fresh The new minfresh value, or <strong>-1</strong> to reset\r
+ * value.\r
+ */\r
+\r
+ public void setMinFresh(int fresh) {\r
+ validate();\r
+ if ( fresh == -1 ) {\r
+ if ( checkDirective(MINFRESH) )\r
+ invalidateByteValue();\r
+ minfresh = -1;\r
+ unsetDirective(MINFRESH);\r
+ } else {\r
+ if ((fresh != minfresh) || ! checkDirective(MINFRESH))\r
+ invalidateByteValue();\r
+ setDirective(MINFRESH);\r
+ minfresh = fresh;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Is the on-if-cached flag value set ?\r
+ * @return A boolean.\r
+ */\r
+\r
+ public boolean checkOnlyIfCached() {\r
+ validate();\r
+ return onlyifcached;\r
+ }\r
+\r
+ /**\r
+ * Set the only-if-cached directive.\r
+ * @param onoff The boolean value for the directive.\r
+ */\r
+\r
+ public void setOnlyIfCached(boolean onoff) {\r
+ validate();\r
+ if ( ! onoff ) {\r
+ if ( onlyifcached ) {\r
+ invalidateByteValue();\r
+ onlyifcached = false;\r
+ }\r
+ unsetDirective(ONLYIFCACHED);\r
+ } else if ( ! onlyifcached ) {\r
+ invalidateByteValue();\r
+ setDirective(ONLYIFCACHED);\r
+ onlyifcached = true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Is the public flag set ?\r
+ * @return A boolean.\r
+ */\r
+\r
+ public boolean checkPublic() {\r
+ validate();\r
+ return pub;\r
+ }\r
+\r
+ /**\r
+ * Set the public directive.\r
+ * @param onoff The public directive value.\r
+ */\r
+\r
+ public void setPublic(boolean onoff) {\r
+ validate();\r
+ if ( ! onoff ) {\r
+ if ( pub ) {\r
+ invalidateByteValue();\r
+ pub = false;\r
+ }\r
+ unsetDirective(PUB);\r
+ } else if ( ! pub ) {\r
+ invalidateByteValue();\r
+ setDirective(PUB);\r
+ pub = true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Check and get the private value.\r
+ * @param def The default value if undefined.\r
+ * @return A list of field-names, as a String array, or the provided\r
+ * default value otherwise.\r
+ */\r
+\r
+ public String[] getPrivate() {\r
+ validate();\r
+ return (priv == null) ? null : priv;\r
+ }\r
+\r
+ /**\r
+ * Set the private directive value.\r
+ * @param priv The list of field-names as a String array.\r
+ */\r
+\r
+ public void setPrivate(String priv[]) {\r
+ validate();\r
+ invalidateByteValue();\r
+ setDirective(PRIV);\r
+ this.priv = priv;\r
+ }\r
+\r
+ /**\r
+ * Unset the <code>private</code> directive.\r
+ */\r
+\r
+ public void unsetPrivate() {\r
+ validate();\r
+ if ( checkDirective(PRIV) )\r
+ invalidateByteValue();\r
+ unsetDirective(PRIV);\r
+ priv = null;\r
+ }\r
+\r
+ /**\r
+ * Is the no-transform flag set ?\r
+ * @return A boolean.\r
+ */\r
+\r
+ public boolean checkNoTransform() {\r
+ validate();\r
+ return notransform;\r
+ }\r
+\r
+ /**\r
+ * Set the no-transform directive.\r
+ * @param onoff The new boolean value for the no-transform directive.\r
+ */\r
+\r
+ public void setNoTransform(boolean onoff) {\r
+ validate();\r
+ if ( ! onoff ) {\r
+ if ( notransform ) {\r
+ invalidateByteValue();\r
+ notransform = false;\r
+ }\r
+ unsetDirective(NOTRANSFORM);\r
+ } else if ( ! notransform ) {\r
+ invalidateByteValue();\r
+ setDirective(NOTRANSFORM);\r
+ notransform = true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Is the must-revalidate flag set ?\r
+ * @return A boolean.\r
+ */\r
+\r
+ public boolean checkMustRevalidate() {\r
+ validate();\r
+ return mustrevalidate;\r
+ }\r
+\r
+ /**\r
+ * Set the must-revalidate directive.\r
+ * @param onoff The new value for the must-revalidate directive.\r
+ */\r
+\r
+ public void setMustRevalidate(boolean onoff) {\r
+ validate();\r
+ if ( ! onoff ) {\r
+ if ( mustrevalidate ) {\r
+ invalidateByteValue();\r
+ mustrevalidate = false;\r
+ }\r
+ unsetDirective(MUSTREVALIDATE);\r
+ } else if ( ! mustrevalidate ) {\r
+ invalidateByteValue();\r
+ setDirective(MUSTREVALIDATE);\r
+ mustrevalidate = true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Is the proxy-revalidate flag set ?\r
+ * @return A boolean.\r
+ */\r
+\r
+ public boolean checkProxyRevalidate() {\r
+ validate();\r
+ return proxyrevalidate;\r
+ }\r
+\r
+ /**\r
+ * Set the proxy-revalidate directive.\r
+ * @param onoff The new proxy-revalidate value.\r
+ */\r
+\r
+ public void setProxyRevalidate(boolean onoff) {\r
+ validate();\r
+ if ( ! onoff ) {\r
+ if ( proxyrevalidate ) {\r
+ invalidateByteValue();\r
+ proxyrevalidate = false;\r
+ }\r
+ unsetDirective(PROXYREVALIDATE);\r
+ } else if ( ! proxyrevalidate ) {\r
+ invalidateByteValue();\r
+ setDirective(PROXYREVALIDATE);\r
+ proxyrevalidate = true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Create a new empty HttpCacheControl object descriptor.\r
+ * @param isValid A boolean indicating if this object will be filled in\r
+ * by parsing a value, or is for internal purposes.\r
+ */\r
+\r
+ HttpCacheControl(boolean isValid) {\r
+ this.raw = null ;\r
+ this.isValid = isValid;\r
+ }\r
+\r
+ /**\r
+ * Create a new empty cache control object descriptor.\r
+ * The value will be provided through parsing.\r
+ */\r
+\r
+ public HttpCacheControl() {\r
+ this(false);\r
+ }\r
+\r
+}\r