0001: // HttpMessage.java
0002: // $Id: HttpMessage.java,v 1.45 2007/02/09 22:05:52 ylafon Exp $
0003: // (c) COPYRIGHT MIT and INRIA, 1996.
0004: // Please first read the full copyright statement in file COPYRIGHT.html
0005:
0006: package org.w3c.www.http;
0007:
0008: import java.io.IOException;
0009: import java.io.OutputStream;
0010:
0011: import java.util.Dictionary;
0012: import java.util.Enumeration;
0013: import java.util.Hashtable;
0014:
0015: import org.w3c.util.ArrayDictionary;
0016: import org.w3c.util.EmptyEnumeration;
0017:
0018: import org.w3c.www.mime.MimeHeaderHolder;
0019: import org.w3c.www.mime.MimeParser;
0020:
0021: /**
0022: * The basic class for all HTTP messages, as define in the HTTP spec.
0023: * This class is the base class for a number of other classes, including
0024: * both the ingoing/outgoing requests and replies.
0025: */
0026:
0027: public class HttpMessage implements MimeHeaderHolder, Cloneable, HTTP {
0028:
0029: // FIXME doc
0030: public final static int EMIT_HEADERS = (1 << 0);
0031: public final static int EMIT_BODY = (1 << 2);
0032: public final static int EMIT_FOOTERS = (1 << 3);
0033: public final static int EMIT_ALL = ((1 << 0) | (1 << 1) | (1 << 2));
0034:
0035: // HTTP message well-known headers
0036: public static int H_CACHE_CONTROL = 0;
0037: public static int H_CONNECTION = 1;
0038: public static int H_PROXY_CONNECTION = 2;
0039: public static int H_DATE = 3;
0040: public static int H_PRAGMA = 4;
0041: public static int H_TRANSFER_ENCODING = 5;
0042: public static int H_UPGRADE = 6;
0043: public static int H_VIA = 7;
0044:
0045: public static int H_PROTOCOL = 8;
0046: public static int H_PROTOCOL_REQUEST = 9;
0047: public static int H_PROTOCOL_INFO = 10;
0048: public static int H_PROTOCOL_QUERY = 11;
0049:
0050: public static int H_SET_COOKIE = 12;
0051: public static int H_COOKIE = 13;
0052:
0053: public static int H_TRAILER = 14;
0054:
0055: public static int H_MAN_EXT = 15;
0056: public static int H_OPT_EXT = 16;
0057: public static int H_CMAN_EXT = 17;
0058: public static int H_COPT_EXT = 18;
0059:
0060: public static int MAX_HEADERS = 61;
0061:
0062: /**
0063: * The header value factory.
0064: */
0065: protected static Hashtable factory = new Hashtable(23);
0066:
0067: /**
0068: * The header value repository.
0069: * At this time, I am using this quite inefficient scheme, but the API
0070: * have been carefully designed to enable a more efficient implementation.
0071: */
0072: protected Dictionary headers = null;
0073: /**
0074: * The major version of this message, according to HTTP specs.
0075: */
0076: protected short major = 1;
0077: /**
0078: * The minoir version of this message, according to HTTP specs.
0079: */
0080: protected short minor = 1;
0081: /**
0082: * The date at which this message was last emitted.
0083: */
0084: protected long emitdate = -1;
0085: /**
0086: * The state dictionary.
0087: */
0088: protected ArrayDictionary state = null;
0089: /**
0090: * The extension namespace counter.
0091: */
0092: private int extCurrentNamespace = 10;
0093:
0094: // FIXME
0095: protected HeaderValue values[] = null;
0096:
0097: protected static HeaderDescription descriptors[] = new HeaderDescription[MAX_HEADERS];
0098:
0099: // Initialize the global header factory
0100:
0101: protected final static void registerHeader(String name, String cls) {
0102: HeaderDescription d = new HeaderDescription(name, cls);
0103: factory.put(d.getName(), d);
0104: }
0105:
0106: protected final static void registerHeader(String name, String c,
0107: int i) {
0108: HeaderDescription d = new HeaderDescription(name, c, i);
0109: descriptors[i] = d;
0110: factory.put(d.getName(), d);
0111: }
0112:
0113: static {
0114: registerHeader("Cache-Control",
0115: "org.w3c.www.http.HttpCacheControl", H_CACHE_CONTROL);
0116: registerHeader("Connection", "org.w3c.www.http.HttpTokenList",
0117: H_CONNECTION);
0118: registerHeader("Proxy-Connection",
0119: "org.w3c.www.http.HttpTokenList", H_PROXY_CONNECTION);
0120: registerHeader("Date", "org.w3c.www.http.HttpDate", H_DATE);
0121: registerHeader("Pragma", "org.w3c.www.http.HttpTokenList",
0122: H_PRAGMA);
0123: registerHeader("Transfer-Encoding",
0124: "org.w3c.www.http.HttpTokenList", H_TRANSFER_ENCODING);
0125: registerHeader("Upgrade", "org.w3c.www.http.HttpTokenList",
0126: H_UPGRADE);
0127: registerHeader("Via", "org.w3c.www.http.HttpCaseTokenList",
0128: H_VIA);
0129: registerHeader("Trailer", "org.w3c.www.http.HttpTokenList",
0130: H_TRAILER);
0131: registerHeader("Protocol", "org.w3c.www.http.HttpBag",
0132: H_PROTOCOL);
0133: registerHeader("Protocol-Request", "org.w3c.www.http.HttpBag",
0134: H_PROTOCOL_REQUEST);
0135: registerHeader("Protocol-Query", "org.w3c.www.http.HttpBag",
0136: H_PROTOCOL_QUERY);
0137: registerHeader("Protocol-Info", "org.w3c.www.http.HttpBag",
0138: H_PROTOCOL_INFO);
0139: registerHeader("Set-Cookie",
0140: "org.w3c.www.http.HttpSetCookieList", H_SET_COOKIE);
0141: registerHeader("Cookie", "org.w3c.www.http.HttpCookieList",
0142: H_COOKIE);
0143: registerHeader("Man", "org.w3c.www.http.HttpExtList", H_MAN_EXT);
0144: registerHeader("Opt", "org.w3c.www.http.HttpExtList", H_OPT_EXT);
0145: registerHeader("C-Man", "org.w3c.www.http.HttpExtList",
0146: H_CMAN_EXT);
0147: registerHeader("C-Opt", "org.w3c.www.http.HttpExtList",
0148: H_COPT_EXT);
0149: }
0150:
0151: /**
0152: * Get a header value, given its name.
0153: * @param name The name of the field whose value is to be fetched.
0154: * @param def The default value if the field is undefined.
0155: */
0156:
0157: public HeaderValue getHeaderValue(String name, HeaderValue def) {
0158: // Check the description, for fast access:
0159: HeaderValue v = null;
0160: HeaderDescription d = (HeaderDescription) factory.get(name);
0161: if (d != null && d.offset >= 0) {
0162: v = values[d.offset];
0163: } else if (headers != null) {
0164: v = (HeaderValue) headers.get(name);
0165: }
0166: return v == null ? def : v;
0167: }
0168:
0169: /**
0170: * Get a header value by name.
0171: * @param name The header's name.
0172: * @return The value of the header, as a String, or
0173: * <strong>null</strong>
0174: * if undefined.
0175: */
0176:
0177: public final HeaderValue getHeaderValue(String name) {
0178: return getHeaderValue(name.toLowerCase(), null);
0179: }
0180:
0181: /**
0182: * Fast access to header value.
0183: * <p>This method provides a very fast access to pre-defined header
0184: * values. You can use it on all headers that have an access token.
0185: * @param idx The token of the header to access.
0186: * @return An instance of <code>HeaderValue</code> or <strong>null
0187: * </strong> if undefined.
0188: */
0189:
0190: public final HeaderValue getHeaderValue(int idx) {
0191: return values[idx];
0192: }
0193:
0194: /**
0195: * Set a header value.
0196: * @param name The name of the header to define.
0197: * @param value It's HeaderValue.
0198: */
0199:
0200: public void setHeaderValue(String name, HeaderValue value) {
0201: String lname = name.toLowerCase();
0202: HeaderDescription d = (HeaderDescription) factory.get(lname);
0203: if (d != null && d.offset >= 0) {
0204: values[d.offset] = value;
0205: } else {
0206: if (headers == null)
0207: headers = new ArrayDictionary(5, 5);
0208: headers.put(lname, value);
0209: }
0210: }
0211:
0212: /**
0213: * Get a header value, keyed by it's header description.
0214: * This is usefull when enumerating headers, by the mean of
0215: * <code>enumerateHeaderDescriptions</code>.
0216: * @param d The header description.
0217: * @return A HeaderValue instance, if the header is defined,
0218: * <strong>null</strong> otherwise.
0219: */
0220:
0221: public HeaderValue getHeaderValue(HeaderDescription d) {
0222: // Try to be as fast as possible:
0223: if (d.offset >= 0) {
0224: return values[d.offset];
0225: } else {
0226: return ((headers != null) ? (HeaderValue) headers.get(d
0227: .getName()) : null);
0228: }
0229: }
0230:
0231: /**
0232: * Set a header value, keyed by it's header description.
0233: * @param d The header description.
0234: * @param v The HeaderValue instance, or <strong>null</strong> to
0235: * reset the header value.
0236: */
0237:
0238: public void setHeaderValue(HeaderDescription d, HeaderValue v) {
0239: if (d.offset >= 0) {
0240: values[d.offset] = v;
0241: } else {
0242: if (headers == null)
0243: headers = new ArrayDictionary(5, 5);
0244: headers.put(d.getName(), v);
0245: }
0246: }
0247:
0248: /**
0249: * Fast write accessor to headers.
0250: * <p> This method provides a very fast write access to header
0251: * values. It can be used with any of the headers that have
0252: * a pre-defined access token.
0253: * @param idx The access token of the header's to write to.
0254: * @param value The new header value.
0255: */
0256:
0257: public final void setHeaderValue(int idx, HeaderValue value) {
0258: values[idx] = value;
0259: }
0260:
0261: /**
0262: * Remove a header, by name.
0263: * @param name The name of the header to remove.
0264: */
0265:
0266: public void removeHeader(String name) {
0267: String lname = name.toLowerCase();
0268: HeaderDescription d = (HeaderDescription) factory.get(lname);
0269: if (d != null) {
0270: if (d.offset >= 0) {
0271: values[d.offset] = null;
0272: } else if (headers != null) {
0273: headers.remove(lname);
0274: }
0275: }
0276: }
0277:
0278: /**
0279: * Remove a header, by address.
0280: * A fast version of the above.
0281: * @param idx The index of the header to remove.
0282: */
0283:
0284: public final void removeHeader(int idx) {
0285: if ((idx >= 0) && (idx < MAX_HEADERS))
0286: values[idx] = null;
0287: }
0288:
0289: /**
0290: * Enumerate all the available headers for that message.
0291: * This method returns an enumeration of HeaderDescription instances,
0292: * which you can then use to access most efficiently header values.
0293: * @param all If <strong>true</strong> the enumeration will cover
0294: * all headers (even the ones that are not defined for that message)
0295: * otherwise, it will cover only defined headers.
0296: * @return An enumeration.
0297: */
0298:
0299: public Enumeration enumerateHeaderDescriptions(boolean all) {
0300: return new headerEnumerator(this , all);
0301: }
0302:
0303: /**
0304: * Enumerate all the headers defined for that message.
0305: * This method returns an enumeration of HeaderDescription instances,
0306: * which you can then use to access most efficiently header values.
0307: * @return An enumeration.
0308: */
0309:
0310: public Enumeration enumerateHeaderDescriptions() {
0311: return new headerEnumerator(this , false);
0312: }
0313:
0314: /**
0315: * State management - Add a piece of state to this request.
0316: * If the piece of state already exists, it is overriden by the new
0317: * value.
0318: * @param name The name of the piece of state to define.
0319: * @param value It's corresponding value, or <strong>null</strong> to
0320: * reset the value.
0321: */
0322:
0323: public void setState(String name, Object value) {
0324: if (value != null) {
0325: if (state == null)
0326: state = new ArrayDictionary(4, 4);
0327: state.put(name, value);
0328: } else if (state != null) {
0329: state.remove(name);
0330: }
0331: }
0332:
0333: /**
0334: * State management - Lookup the value of a state on this request.
0335: * @param name The name of the piece of state to look for.
0336: * @return An object, if the piece of state is defined, <strong>null
0337: * </strong> otherwise.
0338: */
0339:
0340: public Object getState(String name) {
0341: return (state == null) ? null : state.get(name);
0342: }
0343:
0344: /**
0345: * State management - Remove a piece of state from this request.
0346: * @param name The name of the piece of state to remove.
0347: */
0348:
0349: public void delState(String name) {
0350: if (state != null)
0351: state.remove(name);
0352: }
0353:
0354: /**
0355: * State management - Is the given state defined for the message ?
0356: * @return A boolean <strong>true</strong> if the state is defined,
0357: * <strong>false</strong> otherwise.
0358: */
0359:
0360: public boolean hasState(String name) {
0361: return (state != null) && (state.get(name) != null);
0362: }
0363:
0364: /**
0365: * Get an enumeration of the states names.
0366: * @return an Enumeration
0367: */
0368: public Enumeration getStateNames() {
0369: return ((state != null) ? state.keys() : new EmptyEnumeration());
0370: }
0371:
0372: /**
0373: * Get a clone of this HTTP message.
0374: * @return An HttpMessage, of the class of the message receiver.
0375: */
0376:
0377: public HttpMessage getClone() {
0378: try {
0379: // Start by a std clone:
0380: HttpMessage cl = (HttpMessage) clone();
0381: // Then all tables:
0382: cl.values = new HeaderValue[MAX_HEADERS];
0383: System.arraycopy(values, 0, cl.values, 0, MAX_HEADERS);
0384: if (cl.headers != null)
0385: cl.headers = ((ArrayDictionary) ((ArrayDictionary) headers)
0386: .clone());
0387: if (cl.state != null)
0388: cl.state = (ArrayDictionary) state.clone();
0389: return cl;
0390: } catch (Exception ex) {
0391: throw new RuntimeException("Clone not supported !");
0392: }
0393: }
0394:
0395: /**
0396: * Get a clone of this HTTP message.
0397: * It is a semi-deep clone, not a complete one.
0398: * @return An HttpMessage, of the class of the message receiver.
0399: */
0400:
0401: public HttpMessage getDeeperClone() {
0402: try {
0403: // Start by a std clone:
0404: HttpMessage cl = (HttpMessage) clone();
0405: // Then all tables:
0406: cl.values = new HeaderValue[MAX_HEADERS];
0407: for (int i = 0; i < MAX_HEADERS; i++) {
0408: if (values[i] != null) {
0409: cl.values[i] = (HeaderValue) ((BasicValue) values[i])
0410: .clone();
0411: }
0412: }
0413: // that _should_ be ok.
0414: if (cl.headers != null)
0415: cl.headers = ((ArrayDictionary) ((ArrayDictionary) headers)
0416: .clone());
0417: // FIXME need to do a better cloning of that.
0418: if (cl.state != null)
0419: cl.state = (ArrayDictionary) state.clone();
0420: return cl;
0421: } catch (Exception ex) {
0422: throw new RuntimeException("Clone not supported !");
0423: }
0424: }
0425:
0426: /**
0427: * Get a header field value as a String.
0428: * @param name The name of the header.
0429: * @return A String giving the header value, or <strong>null</strong>
0430: * if undefined.
0431: */
0432:
0433: public String getValue(String name) {
0434: HeaderValue value = getHeaderValue(name);
0435: return (value != null) ? value.toExternalForm() : null;
0436: }
0437:
0438: /**
0439: * Get a header field value as a String.
0440: * @param d The header description.
0441: * @return The String value for the given header, or <strong>null</strong>
0442: * if undefined.
0443: */
0444:
0445: public String getValue(HeaderDescription d) {
0446: HeaderValue v = getHeaderValue(d);
0447: return (v == null) ? null : v.toString();
0448: }
0449:
0450: /**
0451: * Define a new header field.
0452: * @param name The name of the header to be defined or reset.
0453: * @param value It's String value, or <strong>null</strong> to reset
0454: * the value.
0455: */
0456:
0457: public void setValue(String name, String strval) {
0458: String lname = name.toLowerCase();
0459: HeaderDescription d = null;
0460: // If reset ing value:
0461: if (strval == null) {
0462: d = (HeaderDescription) factory.get(lname);
0463: if (d != null) {
0464: if (d.offset >= 0) {
0465: values[d.offset] = null;
0466: } else if (headers != null) {
0467: headers.remove(lname);
0468: }
0469: }
0470: return;
0471: }
0472: // Get or create the appropriate value holder:
0473: HeaderValue value = getHeaderValue(lname);
0474: if (value == null) {
0475: if (d == null)
0476: d = (HeaderDescription) factory.get(lname);
0477: if (d == null) {
0478: registerHeader(name, "org.w3c.www.http.HttpString");
0479: value = new HttpString();
0480: } else {
0481: value = d.getHolder();
0482: }
0483: }
0484: // Set (or reset) the byte value:
0485: byte bval[] = new byte[strval.length()];
0486: strval.getBytes(0, bval.length, bval, 0);
0487: value.setBytes(bval, 0, bval.length);
0488: // Register this new header:
0489: setHeaderValue(lname, value);
0490: }
0491:
0492: /**
0493: * Probe this message for a defined header.
0494: * @param name The name of the header to check.
0495: * @return <strong>true</strong> if the header is defined, <strong>
0496: * false</strong> otherwise.
0497: */
0498:
0499: public boolean hasHeader(String name) {
0500: return getHeaderValue(name) != null;
0501: }
0502:
0503: /**
0504: * Probe this message for a defined header, fast access !
0505: * @param idx The index of the well-known header to check.
0506: * @return <strong>true</strong> if the header is defined, <strong>
0507: * false</strong> otherwise.
0508: */
0509:
0510: public boolean hasHeader(int idx) {
0511: return values[idx] != null;
0512: }
0513:
0514: /**
0515: * MimeHeaderHolder implementation - The MIME parser callback.
0516: * This method is called if the HttpMessage is created by parsing
0517: * an input stream. Each time the MIME parser detects a new header
0518: * field, it calls back this method.
0519: * @param name The name of the header that has been encountered.
0520: * @param buf The buffer containing the header value.
0521: * @param off The offset of the header value in the above buffer.
0522: * @param len The length of the header value in the above buffer.
0523: */
0524:
0525: public void notifyHeader(String name, byte buf[], int off, int len) {
0526: // Get the header value repository, or create a new one:
0527: String lname = name.toLowerCase();
0528: HeaderValue value = getHeaderValue(lname);
0529: if (value == null) {
0530: HeaderDescription d = (HeaderDescription) factory
0531: .get(lname);
0532: if (d == null) {
0533: // Slow header access anyway:
0534: value = new HttpString();
0535: if (headers == null)
0536: headers = new ArrayDictionary(5, 5);
0537: registerHeader(name, "org.w3c.www.http.HttpString");
0538: headers.put(lname, value);
0539: } else {
0540: value = d.getHolder();
0541: if (d.offset >= 0) {
0542: values[d.offset] = value;
0543: } else {
0544: if (headers == null)
0545: headers = new ArrayDictionary(5, 5);
0546: headers.put(lname, value);
0547: }
0548: }
0549: }
0550: // Notify the header value of the newly received bunch of bytes:
0551: value.addBytes(buf, off, len);
0552: }
0553:
0554: /**
0555: * MimeHeaderHolder implementation - HTTP message about to be parsed.
0556: * No further action is required at this point (we do not distinguish
0557: * between request or reply here). The MIME parsing is to continue normally
0558: * so we return <strong>false</strong>.
0559: * @return Always <strong>false</strong> to conotinue the MIME parsing.
0560: * @exception HttpParserException if parsing failed.
0561: * @exception IOException if an IO error occurs.
0562: */
0563:
0564: public boolean notifyBeginParsing(MimeParser parser)
0565: throws HttpParserException, IOException {
0566: return false;
0567: }
0568:
0569: /**
0570: * MimeHeaderHolder implementation - HTTP message parsing done.
0571: * Nothing special to be done here, return straight.
0572: * @exception HttpParserException if parsing failed.
0573: * @exception IOException if an IO error occurs.
0574: */
0575:
0576: public void notifyEndParsing(MimeParser parser)
0577: throws HttpParserException, IOException {
0578: return;
0579: }
0580:
0581: /**
0582: * This message is about to be emited.
0583: * Take any appropriate actions.
0584: * @exception IOException if an IO error occurs.
0585: */
0586:
0587: protected void startEmit(OutputStream out, int what)
0588: throws IOException {
0589: return;
0590: }
0591:
0592: /**
0593: * This message has been emited.
0594: * Take any appropriate action.
0595: * @exception IOException if an IO error occurs.
0596: */
0597:
0598: protected void endEmit(OutputStream out, int what)
0599: throws IOException {
0600: return;
0601: }
0602:
0603: /**
0604: * Emit the headers.
0605: * @exception IOException if an IO error occurs.
0606: */
0607: protected void emitHeaders(OutputStream out, int what)
0608: throws IOException {
0609: if ((what & EMIT_HEADERS) != EMIT_HEADERS) {
0610: return;
0611: }
0612: // If no date is set, then it's time to set it ourself:
0613: emitdate = System.currentTimeMillis();
0614: if (!hasHeader(H_DATE)) {
0615: setHeaderValue(H_DATE, new HttpDate(true, emitdate));
0616: }
0617: //Update the Connection Header for hop by hop extensions
0618: String oldconn[] = getConnection();
0619: HttpTokenList connection = null;
0620: if (oldconn != null) {
0621: connection = new HttpTokenList(oldconn);
0622: } else {
0623: connection = new HttpTokenList(new String[0]);
0624: }
0625: HttpExtList extl = getHttpCManExtDecl();
0626: if (extl != null) {
0627: connection.addToken("C-Man", false);
0628: HttpExt exts[] = extl.getHttpExts();
0629: for (int i = 0; i < exts.length; i++) {
0630: HttpExt ext = exts[i];
0631: Dictionary headers = getExtensionHeaders(ext);
0632: Enumeration henum = headers.keys();
0633: while (henum.hasMoreElements()) {
0634: String header = ext.getRealHeader((String) henum
0635: .nextElement());
0636: connection.addToken(header, false);
0637: }
0638: }
0639: }
0640: extl = getHttpCOptExtDecl();
0641: if (extl != null) {
0642: connection.addToken("C-Opt", false);
0643: HttpExt exts[] = extl.getHttpExts();
0644: for (int i = 0; i < exts.length; i++) {
0645: HttpExt ext = exts[i];
0646: Dictionary headers = getExtensionHeaders(ext);
0647: Enumeration henum = headers.keys();
0648: while (henum.hasMoreElements()) {
0649: String header = ext.getRealHeader((String) henum
0650: .nextElement());
0651: connection.addToken(header, false);
0652: }
0653: }
0654: }
0655:
0656: if (hasHeader("C-Ext"))
0657: connection.addToken("C-Ext", false);
0658:
0659: String tokens[] = (String[]) connection.getValue();
0660: if ((tokens != null) && (tokens.length > 0))
0661: setHeaderValue(H_CONNECTION, connection);
0662:
0663: //update cache control for Ext header
0664: if (hasHeader("Ext"))
0665: addNoCache("Ext");
0666:
0667: // Emit well-known headers first:
0668: for (int i = 0; i < MAX_HEADERS; i++) {
0669: HeaderDescription d = descriptors[i];
0670: HeaderValue v = values[i];
0671: if (v instanceof HttpSetCookieList) {
0672: // ugly hack :(
0673: HttpSetCookieList hscl = (HttpSetCookieList) v;
0674: if (hscl.isOriginal()) {
0675: int nbc = hscl.length();
0676: if (nbc == 0) { //the ugliest hack I have ever wrote ;-)
0677: out.write(d.getTitle());
0678: out.write(':');
0679: out.write(' ');
0680: v.emit(out);
0681: out.write('\r');
0682: out.write('\n');
0683: } else {
0684: for (int j = 0; j < nbc; j++) {
0685: out.write(d.getTitle());
0686: out.write(':');
0687: out.write(' ');
0688: hscl.emitCookie(out, j);
0689: out.write('\r');
0690: out.write('\n');
0691: }
0692: }
0693: } else {
0694: int rcs = hscl.copyLength();
0695: for (int j = 0; j < rcs; j++) {
0696: out.write(d.getTitle());
0697: out.write(':');
0698: out.write(' ');
0699: hscl.emitCopyCookie(out, j);
0700: out.write('\r');
0701: out.write('\n');
0702: }
0703: }
0704: } else if (v != null) {
0705: out.write(d.getTitle());
0706: out.write(':');
0707: out.write(' ');
0708: v.emit(out);
0709: out.write('\r');
0710: out.write('\n');
0711: }
0712: }
0713: // Emit extension headers:
0714: if (headers != null) {
0715: Enumeration e = headers.keys();
0716: while (e.hasMoreElements()) {
0717: String n = (String) e.nextElement();
0718: HeaderDescription d = (HeaderDescription) factory
0719: .get(n);
0720: HeaderValue v = (HeaderValue) headers.get(n);
0721: if (v != null) {
0722: out.write(d.getTitle());
0723: out.write(':');
0724: out.write(' ');
0725: v.emit(out);
0726: out.write('\r');
0727: out.write('\n');
0728: }
0729: }
0730: }
0731: out.write('\r');
0732: out.write('\n');
0733: }
0734:
0735: public void dump(OutputStream out) {
0736: try {
0737: emitHeaders(out, EMIT_HEADERS);
0738: } catch (Exception ex) {
0739: }
0740: }
0741:
0742: /**
0743: * Emit this message to the given output stream.
0744: * This methods emits the given message to the stream, after invoking
0745: * the <code>startEmit</code> method. Once the whole message has been
0746: * emited, the <code>endEmit</code> method is called back.
0747: * @param out The output stream to emit the message to.
0748: * @exception IOException If the message couldn't be emited to the
0749: * given stream, due to IO errors.
0750: */
0751:
0752: public void emit(OutputStream out) throws IOException {
0753: startEmit(out, EMIT_ALL);
0754: if (major > 0)
0755: emitHeaders(out, EMIT_ALL);
0756: endEmit(out, EMIT_ALL);
0757: }
0758:
0759: /**
0760: * @param out The output stream to emit the message to.
0761: * @param what (fixme doc)
0762: * @exception IOException If the message couldn't be emited to the
0763: * given stream, due to IO errors.
0764: */
0765: public void emit(OutputStream out, int what) throws IOException {
0766: startEmit(out, what);
0767: emitHeaders(out, what);
0768: endEmit(out, what);
0769: }
0770:
0771: /**
0772: * Header accessor - set the cache control associated with the message.
0773: * This method should not be used in general, it's much more preferable
0774: * to use the various cache control accessors available.
0775: * @param control The cache control policy, or <strong>null</strong>
0776: * to reset the value.
0777: */
0778:
0779: public void setCacheControl(HttpCacheControl control) {
0780: setHeaderValue(H_CACHE_CONTROL, control);
0781: }
0782:
0783: /**
0784: * Header accessor - get the cache control policy.
0785: * @return The current cache control policy, or <strong>null</strong>
0786: * if undefined.
0787: */
0788:
0789: public HttpCacheControl getCacheControl() {
0790: HeaderValue value = getHeaderValue(H_CACHE_CONTROL);
0791: return (value != null) ? (HttpCacheControl) value.getValue()
0792: : null;
0793: }
0794:
0795: /**
0796: * Set the <code>max-age</code> value of the associated cache control.
0797: * This method hides as much as possible, the difference between
0798: * HTTP/1.1 max-age, and HTTP/1.0 expires headers. It will set only
0799: * the appropriate one.
0800: * @param maxage The max-age value, or <strong>-1</strong> to reset the
0801: * value.
0802: */
0803:
0804: public void setMaxAge(int maxage) {
0805: HttpCacheControl cc = getCacheControl();
0806: if (cc == null) {
0807: if (maxage == -1)
0808: return;
0809: setCacheControl(cc = new HttpCacheControl(true));
0810: }
0811: cc.setMaxAge(maxage);
0812: }
0813:
0814: /**
0815: * Get the <code>max-age</code> value for the current cache control.
0816: * @return The max age value, as an integer, or <strong>-1</strong> if
0817: * undefined.
0818: */
0819:
0820: public int getMaxAge() {
0821: HttpCacheControl cc = getCacheControl();
0822: return (cc == null) ? -1 : cc.getMaxAge();
0823: }
0824:
0825: /**
0826: * Set the <code>s-maxage</code> value of the associated cache control.
0827: * Set the s-maxage value on an HTTP/1.1 reply
0828: * @param maxage The max-age value in seconds, or <strong>-1</strong>
0829: * to reset the value.
0830: */
0831:
0832: public void setSMaxAge(int smaxage) {
0833: HttpCacheControl cc = getCacheControl();
0834: if (cc == null) {
0835: setCacheControl(cc = new HttpCacheControl(true));
0836: }
0837: cc.setSMaxAge(smaxage);
0838: }
0839:
0840: /**
0841: * Get the <code>s-maxage</code> value for the current cache control.
0842: * @return The s-maxage value, as an integer (seconds), or
0843: * <strong>-1</strong> if undefined.
0844: */
0845: public int getSMaxAge() {
0846: HttpCacheControl cc = getCacheControl();
0847: return (cc == null) ? -1 : cc.getSMaxAge();
0848: }
0849:
0850: /**
0851: * Get the <code>no-cache</code> directive of the cache control header.
0852: * @return A list of token (potentially empty) encoded as an array of
0853: * String (with 0 length if empty), or <strong>null</strong> if
0854: * undefined.
0855: */
0856:
0857: public String[] getNoCache() {
0858: HttpCacheControl cc = getCacheControl();
0859: return (cc == null) ? null : cc.getNoCache();
0860: }
0861:
0862: /**
0863: * Set the <code>no-cache</code> directive of the cache control header.
0864: * @param nocache A list of headers name encoded as an array of String
0865: * (of length possibly <strong>0</strong>), or <strong>null</strong>
0866: * to reset the value.
0867: */
0868:
0869: public void setNoCache(String nocache[]) {
0870: HttpCacheControl cc = getCacheControl();
0871: if (cc == null) {
0872: if (nocache == null)
0873: return;
0874: setCacheControl(cc = new HttpCacheControl(true));
0875: }
0876: cc.setNoCache(nocache);
0877: }
0878:
0879: /**
0880: * Set the <code>no-cache</code> directive globally.
0881: */
0882:
0883: public void setNoCache() {
0884: HttpCacheControl cc = getCacheControl();
0885: if (cc == null)
0886: setCacheControl(cc = new HttpCacheControl(true));
0887: cc.setNoCache();
0888: }
0889:
0890: /**
0891: * Add the given header name to the <code>no-cache</code> directive.
0892: * @param name The header name to add there.
0893: */
0894:
0895: public void addNoCache(String name) {
0896: HttpCacheControl cc = getCacheControl();
0897: if (cc == null)
0898: setCacheControl(cc = new HttpCacheControl(true));
0899: cc.addNoCache(name);
0900: }
0901:
0902: /**
0903: * Check the <code>no-store</code> directive of the cache control header.
0904: * @return A boolean <strong>true</strong> if set, <strong>false</strong>
0905: * otherwise.
0906: */
0907:
0908: public boolean checkNoStore() {
0909: HttpCacheControl cc = getCacheControl();
0910: return (cc == null) ? false : cc.checkNoStore();
0911: }
0912:
0913: /**
0914: * Set the <code>no-store</code> directive.
0915: * @param onoff Turn it on or off.
0916: */
0917:
0918: public void setNoStore(boolean onoff) {
0919: HttpCacheControl cc = getCacheControl();
0920: if (cc == null) {
0921: if (!onoff)
0922: return;
0923: setCacheControl(cc = new HttpCacheControl(true));
0924: }
0925: cc.setNoStore(onoff);
0926: }
0927:
0928: /**
0929: * Check the <code>only-if-cached</code> directive.
0930: * @return A boolean, <strong>true</strong> if the directive is set,
0931: * <strong>false</strong> otherwise.
0932: */
0933:
0934: public boolean checkOnlyIfCached() {
0935: HttpCacheControl cc = getCacheControl();
0936: return (cc == null) ? false : cc.checkOnlyIfCached();
0937: }
0938:
0939: /**
0940: * Set the <code>only-if-cached</code> directive.
0941: * @param onoff Turn it on or off.
0942: */
0943:
0944: public void setOnlyIfCached(boolean onoff) {
0945: HttpCacheControl cc = getCacheControl();
0946: if (cc == null) {
0947: if (!onoff)
0948: return;
0949: setCacheControl(cc = new HttpCacheControl(true));
0950: }
0951: cc.setOnlyIfCached(onoff);
0952: }
0953:
0954: // FIXME add all the other cache control directive
0955:
0956: /**
0957: * Header accessor - set the connection header value.
0958: * @param tokens The connection tokens as a String array, or <strong>null
0959: * </strong> to reset the value.
0960: */
0961:
0962: public void setConnection(String tokens[]) {
0963: setHeaderValue(H_CONNECTION, ((tokens == null) ? null
0964: : new HttpTokenList(tokens)));
0965: }
0966:
0967: /**
0968: * Header accessor - get the connection header value.
0969: * @return The tokens of the connection header, as a String array, or
0970: * <strong>null</strong> if undefined.
0971: */
0972:
0973: public String[] getConnection() {
0974: HeaderValue value = getHeaderValue(H_CONNECTION);
0975: return (value != null) ? (String[]) value.getValue() : null;
0976: }
0977:
0978: /**
0979: * Add the given header name to the <code>Connection</code> header.
0980: * @param name The name of the header to add to the <code>Connection</code>
0981: * header.
0982: */
0983:
0984: public void addConnection(String name) {
0985: HttpTokenList list = (HttpTokenList) getHeaderValue(H_CONNECTION);
0986: if (list == null) {
0987: String sList[] = new String[1];
0988: sList[0] = name.toLowerCase();
0989: setHeaderValue(H_CONNECTION, new HttpTokenList(sList));
0990: } else {
0991: list.addToken(name, false);
0992: }
0993: }
0994:
0995: /**
0996: * Does the connection header include the given token ?
0997: * @return A boolean.
0998: */
0999:
1000: public boolean hasConnection(String tok) {
1001: HttpTokenList list = (HttpTokenList) getHeaderValue(H_CONNECTION);
1002: return (list == null) ? false : list.hasToken(tok, false);
1003: }
1004:
1005: /**
1006: * Header accessor - set the proxy connection header value.
1007: * @param tokens The connection tokens as a String array, or
1008: * <strong>null</strong> to reset the value.
1009: */
1010:
1011: public void setProxyConnection(String tokens[]) {
1012: setHeaderValue(H_PROXY_CONNECTION, ((tokens == null) ? null
1013: : new HttpTokenList(tokens)));
1014: }
1015:
1016: /**
1017: * Add the given header name to the <code>Proxy-Connection</code> header.
1018: * @param name The name of the header to add to the
1019: * <code>Proxy-Connection</code> header.
1020: */
1021:
1022: public void addProxyConnection(String name) {
1023: HttpTokenList list = (HttpTokenList) getHeaderValue(H_PROXY_CONNECTION);
1024: if (list == null) {
1025: String sList[] = new String[1];
1026: sList[0] = name.toLowerCase();
1027: setHeaderValue(H_PROXY_CONNECTION, new HttpTokenList(sList));
1028: } else {
1029: list.addToken(name, false);
1030: }
1031: }
1032:
1033: /**
1034: * Header accessor - get the proxy connection header value.
1035: * @return The tokens of the connection header, as a String array,
1036: * or <strong>null</strong> if undefined.
1037: */
1038:
1039: public String[] getProxyConnection() {
1040: HeaderValue value = getHeaderValue(H_PROXY_CONNECTION);
1041: return (value != null) ? (String[]) value.getValue() : null;
1042: }
1043:
1044: /**
1045: * Does the proxy connection header defines the given token.
1046: * @param tok The token to check for.
1047: * @return A boolean.
1048: */
1049:
1050: public boolean hasProxyConnection(String tok) {
1051: HttpTokenList l = (HttpTokenList) getHeaderValue(H_PROXY_CONNECTION);
1052: return (l == null) ? false : l.hasToken(tok, false);
1053: }
1054:
1055: /**
1056: * Header accessor - set the date of this message.
1057: * @param date The date of the message, following Java runtime conventions
1058: * (number of milliseconds since epoch), or <strong>-1</strong> to
1059: * reset the value.
1060: */
1061:
1062: public void setDate(long date) {
1063: setHeaderValue(H_DATE, ((date == -1) ? null : new HttpDate(
1064: true, date)));
1065: }
1066:
1067: /**
1068: * Header accessor - get the date of this message.
1069: * @return A long giving the date of this message, following the Java
1070: * runtime convention (milliseconds since epoch), or <strong>-1</strong>
1071: * if undefined.
1072: */
1073:
1074: public long getDate() {
1075: HeaderValue date = getHeaderValue(H_DATE);
1076: return (date != null) ? ((Long) date.getValue()).longValue()
1077: : -1;
1078: }
1079:
1080: /**
1081: * Header accessor - set the pragmas applicable to this message.
1082: * @param tokens The pragma tokens as a String array, or <strong>null
1083: * </strong> to reset the value.
1084: */
1085:
1086: public void setPragma(String tokens[]) {
1087: setHeaderValue(H_PRAGMA, ((tokens == null) ? null
1088: : new HttpTokenList(tokens)));
1089: }
1090:
1091: /**
1092: * Header accessor - get the pragmas applicable to this message.
1093: * @return The pragma tokens applicable to this message, encoded
1094: * as a String array, or <strong>null</strong> if undefined.
1095: */
1096:
1097: public String[] getPragma() {
1098: HeaderValue value = getHeaderValue(H_PRAGMA);
1099: return (value != null) ? (String[]) value.getValue() : null;
1100: }
1101:
1102: /**
1103: * Header accessor - Check for a given pragma.
1104: * @param pragma The pragma to check for.
1105: * @return A boolean <strong>true</strong> if this pragma is set,
1106: * <strong>false</strong> otherwise.
1107: */
1108:
1109: public boolean hasPragma(String pragma) {
1110: HttpTokenList list = (HttpTokenList) getHeaderValue(H_PRAGMA);
1111: return (list != null) ? list.hasToken(pragma, false) : false;
1112: }
1113:
1114: /**
1115: * Add the given directive to the <code>Pragma</code> header.
1116: * @param name The name of the directive to add to the <code>Pragma</code>
1117: * header.
1118: */
1119:
1120: public void addPragma(String name) {
1121: HttpTokenList list = (HttpTokenList) getHeaderValue(H_PRAGMA);
1122: if (list == null) {
1123: String sList[] = new String[1];
1124: sList[0] = name.toLowerCase();
1125: setHeaderValue(H_PRAGMA, new HttpTokenList(sList));
1126: } else {
1127: list.addToken(name, false);
1128: }
1129: }
1130:
1131: /**
1132: * Header accessor - set the transfer encoding for this message.
1133: * This just sets the transfer encoding, it is up to the rest of the
1134: * application to make sure that the encoding is actually applied
1135: * at emiting time.
1136: * @param tokens The transfer encoding tokens as a String array, or
1137: * <strong>null</strong> to reset the value.
1138: */
1139:
1140: public void setTransferEncoding(String tokens[]) {
1141: setHeaderValue(H_TRANSFER_ENCODING, ((tokens == null) ? null
1142: : new HttpTokenList(tokens)));
1143: }
1144:
1145: /**
1146: * Add an encoding token to the given reply stream (ie the body).
1147: * @param name The name of the encoding to add.
1148: */
1149:
1150: public void addTransferEncoding(String name) {
1151: HttpTokenList l = (HttpTokenList) getHeaderValue(H_TRANSFER_ENCODING);
1152: if (l == null) {
1153: String sList[] = new String[1];
1154: sList[0] = name.toLowerCase();
1155: setHeaderValue(H_TRANSFER_ENCODING,
1156: new HttpTokenList(sList));
1157: } else {
1158: l.addToken(name, false);
1159: }
1160: }
1161:
1162: /**
1163: * Header accessor - get the transfer encoding applying to this message.
1164: * @return The list of encoding tokens, as a String array, or <strong>
1165: * null</strong> if undefined.
1166: */
1167:
1168: public String[] getTransferEncoding() {
1169: HeaderValue value = getHeaderValue(H_TRANSFER_ENCODING);
1170: return (value != null) ? (String[]) value.getValue() : null;
1171: }
1172:
1173: /**
1174: * Header accessor - Check for a given transfer encoding.
1175: * @param encoding The pragma to check for.
1176: * @return A boolean <strong>true</strong> if this encoding is set,
1177: * <strong>false</strong> otherwise.
1178: */
1179:
1180: public boolean hasTransferEncoding(String encoding) {
1181: HttpTokenList l = (HttpTokenList) getHeaderValue(H_TRANSFER_ENCODING);
1182: return (l != null) ? l.hasToken(encoding, false) : false;
1183: }
1184:
1185: /**
1186: * Header accessor - set the upgrade header of this message.
1187: * @param products An array of products you want this message to carry
1188: * or <strong>null</strong> to reset the value.
1189: */
1190:
1191: public void setUpgrade(String products[]) {
1192: setHeaderValue(H_UPGRADE, ((products == null) ? null
1193: : new HttpTokenList(products)));
1194: }
1195:
1196: /**
1197: * Header accessor - get the upgrade header of this message.
1198: * @return A list of products, encoded as an array of String
1199: * or <strong>null</strong> if undefined.
1200: */
1201:
1202: public String[] getUpgrade() {
1203: HeaderValue value = getHeaderValue(H_UPGRADE);
1204: return (value != null) ? (String[]) value.getValue() : null;
1205: }
1206:
1207: /**
1208: * Header accessor - set the Via header of this message.
1209: * @param vias The hops to be placed in the <code>Via</code> header, or
1210: * <strong>null</strong> to reset the value.
1211: */
1212:
1213: public void setVia(String vias[]) {
1214: setHeaderValue(H_VIA, ((vias == null) ? null
1215: : new HttpTokenList(vias)));
1216: }
1217:
1218: /**
1219: * Header accessor - get the via header of this message.
1220: * @return A Via array describing each hop of the message, or <strong>
1221: * null</strong> if undefined.
1222: */
1223:
1224: public String[] getVia() {
1225: HeaderValue value = getHeaderValue(H_VIA);
1226: return (value != null) ? (String[]) value.getValue() : null;
1227: }
1228:
1229: /**
1230: * Add a via clause to the via header.
1231: * @param via The new via clause.
1232: */
1233:
1234: public void addVia(String via) {
1235: HttpTokenList list = (HttpTokenList) getHeaderValue(H_VIA);
1236: if (list == null) {
1237: String sList[] = new String[1];
1238: sList[0] = via;
1239: setVia(sList);
1240: } else {
1241: list.addToken(via, true);
1242: }
1243: }
1244:
1245: /**
1246: * Get the set of protocol extensions that have been applied to that
1247: * that message.
1248: * @return A bag containing the description of the protocol extensions
1249: * applied to that message, or <strong>null</strong>.
1250: */
1251:
1252: public HttpBag getProtocol() {
1253: HeaderValue value = getHeaderValue(H_PROTOCOL);
1254: return (value != null) ? (HttpBag) value.getValue() : null;
1255: }
1256:
1257: /**
1258: * Set the protocol extensions applied to that message.
1259: * @param protocols A bag instance, describing the protocol extensions
1260: * applied to the message, or <strong>null</strong> to reset previous
1261: * value.
1262: */
1263:
1264: public void setProtocol(HttpBag bag) {
1265: setHeaderValue(H_PROTOCOL, bag);
1266: }
1267:
1268: /**
1269: * Get the set of protocol extensions requested by this message.
1270: * @return A bag containing the description of the protocol extensions
1271: * requested by this message, or <strong>null</strong>.
1272: */
1273:
1274: public HttpBag getProtocolRequest() {
1275: HeaderValue value = getHeaderValue(H_PROTOCOL_REQUEST);
1276: return (value != null) ? (HttpBag) value.getValue() : null;
1277: }
1278:
1279: /**
1280: * Set the protocol extensions required by this message.
1281: * @param protocols A bag instance, describing the protocol extensions
1282: * required by the message, or <strong>null</strong> to reset previous
1283: * value.
1284: */
1285:
1286: public void setProtocolRequest(HttpBag bag) {
1287: setHeaderValue(H_PROTOCOL_REQUEST, bag);
1288: }
1289:
1290: /**
1291: * Get the protocol extensions informations carried by this message.
1292: * @return A bag containing the description of the protocol extensions
1293: * informations carried by that message, or <strong>null</strong>.
1294: */
1295:
1296: public HttpBag getProtocolInfo() {
1297: HeaderValue value = getHeaderValue(H_PROTOCOL_INFO);
1298: return (value != null) ? (HttpBag) value.getValue() : null;
1299: }
1300:
1301: /**
1302: * Attach protocol extensions informations to that message.
1303: * @param protocols A bag instance, describing the protocol extensions
1304: * informations to attach to the message, or <strong>null</strong> to
1305: * reset previous value.
1306: */
1307:
1308: public void setProtocolInfo(HttpBag bag) {
1309: setHeaderValue(H_PROTOCOL_INFO, bag);
1310: }
1311:
1312: /**
1313: * Get the set of protocol extensions that are queried through this
1314: * message.
1315: * @return A bag containing the description of the protocol extensions
1316: * queried by that message, or <strong>null</strong>.
1317: */
1318:
1319: public HttpBag getProtocolQuery() {
1320: HeaderValue value = getHeaderValue(H_PROTOCOL_QUERY);
1321: return (value != null) ? (HttpBag) value.getValue() : null;
1322: }
1323:
1324: /**
1325: * Set the protocol extensions queried by that message.
1326: * @param protocols A bag instance, describing the protocol extensions
1327: * queried by the message, or <strong>null</strong> to reset previous
1328: * value.
1329: */
1330:
1331: public void setProtocolQuery(HttpBag bag) {
1332: setHeaderValue(H_PROTOCOL_QUERY, bag);
1333: }
1334:
1335: /**
1336: * Get this message trailer
1337: * @return A list of encoding tokens, encoded as a String array, or
1338: * <strong>null</strong> if undefined.
1339: */
1340:
1341: public String[] getTrailer() {
1342: HeaderValue value = getHeaderValue(H_TRAILER);
1343: return (value != null) ? (String[]) value.getValue() : null;
1344: }
1345:
1346: /**
1347: * Set this message trailer
1348: * @param encodings A list of encoding tokens, encoded as a String array
1349: * or <strong>null</strong> to reset the value.
1350: */
1351:
1352: public void setTrailer(String trailers[]) {
1353: setHeaderValue(H_TRAILER, ((trailers == null) ? null
1354: : new HttpTokenList(trailers)));
1355: }
1356:
1357: /**
1358: * Get the value of the SetCookie header.
1359: * @return AN HttpSetCookie instance, or <strong>null</strong> if
1360: * undefined.
1361: */
1362:
1363: public HttpSetCookieList getSetCookie() {
1364: HeaderValue value = getHeaderValue(H_SET_COOKIE);
1365: return (value != null) ? (HttpSetCookieList) value.getValue()
1366: : null;
1367: }
1368:
1369: /**
1370: * Set the value of the Set-Cookie header.
1371: * @param setcookies The HttpSetCookie value.
1372: */
1373:
1374: public void setSetCookie(HttpSetCookieList setcookie) {
1375: setHeaderValue(H_SET_COOKIE, setcookie);
1376: }
1377:
1378: /**
1379: * Get the cookies attached to that message.
1380: * @return An instance of HttpCookie holding the list of available
1381: * cookies, or <strong>null</strong> if undefined.
1382: */
1383:
1384: public HttpCookieList getCookie() {
1385: HeaderValue value = getHeaderValue(H_COOKIE);
1386: return (value != null) ? (HttpCookieList) value.getValue()
1387: : null;
1388: }
1389:
1390: /**
1391: * Set the cookies attached to this message.
1392: * @param cookies The HttpCookie instance describing the cookies, or
1393: * <strong>null</strong> to reset value.
1394: */
1395:
1396: public void setCookie(HttpCookieList cookie) {
1397: setHeaderValue(H_COOKIE, cookie);
1398: }
1399:
1400: /**
1401: * Get the String identifying the HTTP version used for this message.
1402: * @return A String identifying the protocol version.
1403: */
1404:
1405: public String getVersion() {
1406: switch (major) {
1407: case 0:
1408: switch (minor) {
1409: case 9:
1410: return "HTTP/0.9";
1411: }
1412: break;
1413: case 1:
1414: switch (minor) {
1415: case 0:
1416: return "HTTP/1.0";
1417: case 1:
1418: return "HTTP/1.1";
1419: }
1420: }
1421: return "HTTP/" + major + "." + minor;
1422: }
1423:
1424: /**
1425: * Get the major version number of this message.
1426: * This method returns the major version that the caller should use to
1427: * <em>drive</em> message processing. It <em>may not</em> match the
1428: * version number actually emitted on the wire, which is computed
1429: * by the API itself.
1430: * @return A ninteger giving the major version number.
1431: */
1432:
1433: public short getMajorVersion() {
1434: return major;
1435: }
1436:
1437: /**
1438: * Get the minor version number of this message.
1439: * This method returns the minor version that the caller should use
1440: * to drive message processing. It <em>may not</em> match the
1441: * minor version number emitted on the wire, which is computed by the
1442: * API itself.
1443: * @return An integer giving the minor version number.
1444: */
1445:
1446: public short getMinorVersion() {
1447: return minor;
1448: }
1449:
1450: /**
1451: * Get the date at which this message was last emitted, if ever it was.
1452: * @return The date, in milliseconds since Java epoch at which this message
1453: * was emitted, or <strong>-1</strong> if the message was never emitted.
1454: */
1455:
1456: public long getEmitDate() {
1457: return emitdate;
1458: }
1459:
1460: /**
1461: * Get an Http Extension Listfrom the following list:
1462: * <ul>
1463: * <li>Mandatory (End-to-End) Extensions
1464: * <li>Mandatory (Hop-by-Hop) Extensions
1465: * <li>Optionnal (End-to-End) Extensions
1466: * <li>Optionnal (hop-by-Hop) Extensions
1467: * </ul>
1468: * @param ext the Extension id
1469: * @return a HttpExtList containing the extension declaration (or null)
1470: */
1471: public HttpExtList getExtList(String id) {
1472: HttpExtList extlist = getHttpManExtDecl();
1473: HttpExt ext = (extlist != null ? extlist.getHttpExt(id) : null);
1474: if (ext == null) {
1475: extlist = getHttpCManExtDecl();
1476: ext = (extlist != null ? extlist.getHttpExt(id) : null);
1477: if (ext == null) {
1478: extlist = getHttpOptExtDecl();
1479: ext = (extlist != null ? extlist.getHttpExt(id) : null);
1480: if (ext == null) {
1481: extlist = getHttpCOptExtDecl();
1482: ext = (extlist != null ? extlist.getHttpExt(id)
1483: : null);
1484: if (ext == null) {
1485: extlist = null;
1486: }
1487: }
1488: }
1489: }
1490: return extlist;
1491: }
1492:
1493: /**
1494: * get the String value of the given header relative to the given
1495: * Extension. This method search the header in the following declarations:
1496: * <ul>
1497: * <li>Mandatory (End-to-End) Extensions
1498: * <li>Mandatory (Hop-by-Hop) Extensions
1499: * <li>Optionnal (End-to-End) Extensions
1500: * <li>Optionnal (hop-by-Hop) Extensions
1501: * </ul>
1502: * @param ext the extension
1503: * @param header the extension header
1504: * @return a String (or null)
1505: */
1506: public String getExtHeader(String ext, String header) {
1507: String value = getManExtHeader(ext, header);
1508: if (value == null) {
1509: value = getCManExtHeader(ext, header);
1510: if (value == null) {
1511: value = getOptExtHeader(ext, header);
1512: if (value == null) {
1513: value = getCOptExtHeader(ext, header);
1514: }
1515: }
1516: }
1517: return value;
1518: }
1519:
1520: /**
1521: * get the String value of the given header relative to the given
1522: * Extension. This method search the header in the following declarations:
1523: * <ul>
1524: * <li>Mandatory (End-to-End) Extensions
1525: * </ul>
1526: * @param ext the extension
1527: * @param header the extension header
1528: * @return a String (or null)
1529: */
1530: public String getManExtHeader(String ext, String header) {
1531: return getExtHeader(getHttpManExtDecl(), ext, header);
1532: }
1533:
1534: /**
1535: * get the String value of the given header relative to the given
1536: * Extension. This method search the header in the following declarations:
1537: * <ul>
1538: * <li>Optionnal (End-to-End) Extensions
1539: * </ul>
1540: * @param ext the extension
1541: * @param header the extension header
1542: * @return a String (or null)
1543: */
1544: public String getOptExtHeader(String ext, String header) {
1545: return getExtHeader(getHttpOptExtDecl(), ext, header);
1546: }
1547:
1548: /**
1549: * get the String value of the given header relative to the given
1550: * Extension. This method search the header in the following declarations:
1551: * <ul>
1552: * <li>Mandatory (Hop-by-Hop) Extensions
1553: * </ul>
1554: * @param ext the extension
1555: * @param header the extension header
1556: * @return a String (or null)
1557: */
1558: public String getCManExtHeader(String ext, String header) {
1559: return getExtHeader(getHttpCManExtDecl(), ext, header);
1560: }
1561:
1562: /**
1563: * get the String value of the given header relative to the given
1564: * Extension. This method search the header in the following declarations:
1565: * <ul>
1566: * <li>Optionnal (hop-by-Hop) Extensions
1567: * </ul>
1568: * @param ext the extension
1569: * @param header the extension header
1570: * @return a String (or null)
1571: */
1572: public String getCOptExtHeader(String ext, String header) {
1573: return getExtHeader(getHttpCOptExtDecl(), ext, header);
1574: }
1575:
1576: private String getExtHeader(HttpExtList list, String ext,
1577: String header) {
1578: if (list == null) {
1579: return null;
1580: }
1581: HttpExt extheader = list.getHttpExt(ext);
1582: if (extheader != null) {
1583: String realheader = extheader.getNamespace() + "-" + header;
1584: return getValue(realheader);
1585: }
1586: return null;
1587: }
1588:
1589: /**
1590: * Get The Mandatory (End-to-End) Extension declaration list.
1591: * @return a HttpExtList instance or null;
1592: */
1593: public HttpExtList getHttpManExtDecl() {
1594: HeaderValue value = getHeaderValue(H_MAN_EXT);
1595: HttpExtList list = null;
1596: if (value != null) {
1597: list = (HttpExtList) value.getValue();
1598: if (list != null) {
1599: list.setManOptFlag(HttpExtList.MAN);
1600: }
1601: }
1602: return list;
1603: }
1604:
1605: /**
1606: * Set The Mandatory (End-to-End) Extension declaration list.
1607: * @param exts the extension declaration list.
1608: */
1609: public void setHttpManExtDecl(HttpExtList exts) {
1610: exts.setManOptFlag(HttpExtList.MAN);
1611: setNamespaces(exts);
1612: setHeaderValue(H_MAN_EXT, exts);
1613: }
1614:
1615: /**
1616: * Get The Mandatory (Hop-by-Hop) Extension declaration list.
1617: * @return a HttpExtList instance or null;
1618: */
1619: public HttpExtList getHttpCManExtDecl() {
1620: HeaderValue value = getHeaderValue(H_CMAN_EXT);
1621: HttpExtList list = null;
1622: if (value != null) {
1623: list = (HttpExtList) value.getValue();
1624: if (list != null) {
1625: list.setManOptFlag(HttpExtList.CMAN);
1626: }
1627: }
1628: return list;
1629: }
1630:
1631: /**
1632: * Set the Extension declaration.
1633: * WARNING: The ManOpt flag of exts must have been set.
1634: * @param exts the extension declaration list.
1635: */
1636: public void setHttpExtDecl(HttpExtList exts) {
1637: setNamespaces(exts);
1638: switch (exts.getManOptFlag()) {
1639: case HttpExtList.MAN:
1640: setHeaderValue(H_MAN_EXT, exts);
1641: break;
1642: case HttpExtList.CMAN:
1643: setHeaderValue(H_CMAN_EXT, exts);
1644: break;
1645: case HttpExtList.OPT:
1646: setHeaderValue(H_OPT_EXT, exts);
1647: break;
1648: case HttpExtList.COPT:
1649: setHeaderValue(H_COPT_EXT, exts);
1650: break;
1651: default:
1652: setHeaderValue(H_MAN_EXT, exts);
1653: }
1654: }
1655:
1656: /**
1657: * Set The Mandatory (Hop-by-Hop) Extension declaration list.
1658: * @param exts the extension declaration list.
1659: */
1660: public void setHttpCManExtDecl(HttpExtList exts) {
1661: exts.setManOptFlag(HttpExtList.CMAN);
1662: setNamespaces(exts);
1663: setHeaderValue(H_CMAN_EXT, exts);
1664: }
1665:
1666: /**
1667: * Get The Optionnal (End-to-End) Extension declaration list.
1668: * @return a HttpExtList instance or null;
1669: */
1670: public HttpExtList getHttpOptExtDecl() {
1671: HeaderValue value = getHeaderValue(H_OPT_EXT);
1672: HttpExtList list = null;
1673: if (value != null) {
1674: list = (HttpExtList) value.getValue();
1675: if (list != null) {
1676: list.setManOptFlag(HttpExtList.OPT);
1677: }
1678: }
1679: return list;
1680: }
1681:
1682: /**
1683: * Set The Optional (End-to-End) Extension declaration list.
1684: * @param exts the extension declaration list.
1685: */
1686: public void setHttpOptExtDecl(HttpExtList exts) {
1687: exts.setManOptFlag(HttpExtList.OPT);
1688: setNamespaces(exts);
1689: setHeaderValue(H_OPT_EXT, exts);
1690: }
1691:
1692: /**
1693: * Get The Optionnal (Hop-by-Hop) Extension declaration list.
1694: * @return a HttpExtList instance or null;
1695: */
1696: public HttpExtList getHttpCOptExtDecl() {
1697: HeaderValue value = getHeaderValue(H_COPT_EXT);
1698: HttpExtList list = null;
1699: if (value != null) {
1700: list = (HttpExtList) value.getValue();
1701: if (list != null) {
1702: list.setManOptFlag(HttpExtList.COPT);
1703: }
1704: }
1705: return list;
1706: }
1707:
1708: /**
1709: * Set The Optional (Hop-by-Hop) Extension declaration list.
1710: * @param exts the extension declaration list.
1711: */
1712: public void setHttpCOptExtDecl(HttpExtList exts) {
1713: exts.setManOptFlag(HttpExtList.COPT);
1714: setNamespaces(exts);
1715: setHeaderValue(H_COPT_EXT, exts);
1716: }
1717:
1718: protected void setNamespaces(HttpExtList extl) {
1719: HttpExt exts[] = extl.getHttpExts();
1720: for (int i = 0; i < exts.length; i++) {
1721: if (exts[i].isGenerated())
1722: throw new HttpExtException(
1723: "This extension Object is already "
1724: + "associated to an HttpMessage: "
1725: + exts[i].getName());
1726: if (exts[i].needsHeaders())
1727: exts[i].setNamespace(generateExtNamespace());
1728: }
1729: }
1730:
1731: /**
1732: * Get the headers relative to the given Http Extension declaration.
1733: * @param ext the HttpExt
1734: * @return a Dictionnary of <String, HeaderValue>
1735: */
1736: public Dictionary getExtensionHeaders(HttpExt ext) {
1737: ArrayDictionary extheaders = new ArrayDictionary(5, 5);
1738: if (headers != null) {
1739: Enumeration henum = headers.keys();
1740: String namespace = ext.getNamespace();
1741:
1742: if (namespace == null) {
1743: return extheaders;
1744: }
1745:
1746: namespace += "-";
1747:
1748: while (henum.hasMoreElements()) {
1749: String name = (String) henum.nextElement();
1750: if (name.startsWith(namespace)) {
1751: //remove namespace
1752: String realname = name.substring(3);
1753: extheaders.put(realname, headers.get(name));
1754: }
1755: }
1756: }
1757: return extheaders;
1758: }
1759:
1760: /**
1761: * Set an extension header relative to the given extension declaration.
1762: * @param ext The extension declaration
1763: * @param name the header name
1764: * @param value the header value
1765: */
1766: public synchronized void setExtensionHeader(HttpExt ext,
1767: String name, String value) {
1768: if (ext.isGenerated())
1769: throw new HttpExtException(
1770: "This extension Object is already "
1771: + "associated to an HttpMessage: "
1772: + ext.getName());
1773: String namespace = ext.getNamespace();
1774: if (namespace == null) {
1775: namespace = generateExtNamespace();
1776: ext.setNamespace(namespace);
1777: }
1778: setValue(namespace + "-" + name, value);
1779: }
1780:
1781: /**
1782: * get a new namespace.
1783: * @return an int.
1784: */
1785: protected synchronized String generateExtNamespace() {
1786: return String.valueOf(extCurrentNamespace++);
1787: }
1788:
1789: public void setEnd2EndExtensionAcknowledgmentHeader() {
1790: setValue("Ext", "");
1791: }
1792:
1793: public void setHopByHopExtensionAcknowledgmentHeader() {
1794: setValue("C-Ext", "");
1795: }
1796:
1797: public final static void registerExtHeader(String name, String cls) {
1798: registerHeader(name, cls);
1799: }
1800:
1801: public HttpMessage(MimeParser parser) {
1802: // FIXME
1803: this .values = new HeaderValue[MAX_HEADERS];
1804: }
1805:
1806: public HttpMessage() {
1807: // FIXME
1808: this .values = new HeaderValue[MAX_HEADERS];
1809: }
1810:
1811: }
|