001: /*
002: * (C) Copyright IBM Corp. 2000 All rights reserved.
003: *
004: * The program is provided "AS IS" without any warranty express or
005: * implied, including the warranty of non-infringement and the implied
006: * warranties of merchantibility and fitness for a particular purpose.
007: * IBM will not be liable for any damages suffered by you as a result
008: * of using the Program. In no event will IBM be liable for any
009: * special, indirect or consequential damages or lost profits even if
010: * IBM has been advised of the possibility of their occurrence. IBM
011: * will not be liable for any third party claims against you.
012: *
013: * Portions Copyright (C) Simulacra Media Ltd, 2004.
014: */
015:
016: package com.ibm.webdav;
017:
018: import java.io.IOException;
019:
020: /*
021: * (C) Copyright IBM Corp. 2000 All rights reserved.
022: *
023: * The program is provided "AS IS" without any warranty express or
024: * implied, including the warranty of non-infringement and the implied
025: * warranties of merchantibility and fitness for a particular purpose.
026: * IBM will not be liable for any damages suffered by you as a result
027: * of using the Program. In no event will IBM be liable for any
028: * special, indirect or consequential damages or lost profits even if
029: * IBM has been advised of the possibility of their occurrence. IBM
030: * will not be liable for any third party claims against you.
031: */
032: import java.util.Properties;
033:
034: import sun.misc.BASE64Decoder;
035: import sun.misc.BASE64Encoder;
036:
037: /** A HTTPHeaders represents additional information about the resource
038: * that may effect how a method is executed, or reflect information that
039: * is returned from a method execution. These methods correspond to the
040: * HTTP/1.1 and WebDAV request and response Headers. Method names correspond
041: * to the Header names after suitable translation to Java syntax. Not all
042: * HTTP/1.1 headers are included, but all headers are supported through
043: * the <code>get</code> and <code>put</code> methods. The method descriptions
044: * are brief. For further details, see the HTTP/1.1 specification, section 14,
045: * and the WebDAV specification, section 9.
046: * <p>
047: * Values for the request context are set before calling a method of
048: * Resource or Collection, and provide additional parameters for
049: * the method or context in which it is executed. After the method returns,
050: * additional information about the method execution is available in the
051: * context.</p>
052: * <p>
053: * Many of these headers are only used internally by the ResourceHTTPImpl
054: * class to marshall arguments between the client and server using the HTTP
055: * protocol. Most of this information can be more conveniently obtained through
056: * the parameters and return values of class Resource.</p>
057: * <p>
058: * Since header names are case insensitive, all headers are
059: * converted to lower case before being used to search for context information.
060: * @author Jim Amsden <jamsden@us.ibm.com>
061: */
062: public class HTTPHeaders extends Properties {
063: public static HTTPHeaders defaults = new HTTPHeaders();
064:
065: static {
066: defaults.put("connection", "close");
067:
068: defaults.put("accept", "text/xml");
069:
070: // defaults.put("depth", Collection.allMembers);
071: // defaults.put("overwrite", "F");
072: }
073:
074: // used for authorization headers
075: static BASE64Encoder base64encoder = new BASE64Encoder();
076: static BASE64Decoder base64decoder = new BASE64Decoder();
077:
078: /** The default constructor for a ResourceContext.
079: */
080: public HTTPHeaders() {
081: super ();
082: }
083:
084: /** Construct a HTTPHeaders instance with a set of default values.
085: * @param defaults default values for the new resource context
086: */
087: public HTTPHeaders(HTTPHeaders defaults) {
088: super (defaults);
089: }
090:
091: /** Get what media types are acceptable for a response.
092: */
093: public String accept() {
094: return getProperty("accept");
095: }
096:
097: /** Set what media types are acceptable for a response.
098: */
099: public void accept(String value) {
100: put("accept", value);
101: }
102:
103: /** Get what character sets are acceptable for a response.
104: */
105: public String acceptCharset() {
106: return getProperty("accept-charset");
107: }
108:
109: /** Set what character sets are acceptable for a response.
110: */
111: public void acceptCharset(String value) {
112: put("accept-charset", value);
113: }
114:
115: /** Get what content-encoding values are acceptable for a response.
116: */
117: public String acceptEncoding() {
118: return getProperty("accept-encoding");
119: }
120:
121: /** Get what content-encoding values are acceptable for a response.
122: */
123: public void acceptEncoding(String value) {
124: put("accept-encoding", value);
125: }
126:
127: /** Get what natural languages are acceptable for a response.
128: */
129: public String acceptLanguage() {
130: return getProperty("accept-language");
131: }
132:
133: /** Set what natural languages are acceptable for a response.
134: */
135: public void acceptLanguage(String value) {
136: put("accept-language", value);
137: }
138:
139: /** Get the range requests acceptable to a server.
140: */
141: public String acceptRanges() {
142: return getProperty("accept-ranges");
143: }
144:
145: /** Set the range requests acceptable to a server.
146: */
147: public void acceptRanges(String value) {
148: put("accept-ranges", value);
149: }
150:
151: /** Get the sender's estimate of the time since the response was generated.
152: */
153: public String age() {
154: return getProperty("age");
155: }
156:
157: /** Set the sender's estimate of the time since the response was generated.
158: */
159: public void age(String value) {
160: put("age", value);
161: }
162:
163: /** Get methods allowed on a resource
164: */
165: public String allow() {
166: return getProperty("allow");
167: }
168:
169: /** Set methods allowed on a resource
170: */
171: public void allow(String value) {
172: put("allow", value);
173: }
174:
175: /** Get the user's credentials for the realm of the resource being requested.
176: */
177: public String authorization() {
178: return getProperty("authorization");
179: }
180:
181: /** Set the user's credentials for the realm of the resource being requested.
182: * @see com.ibm.webdav.ResourceContext#setBasicAuthorization
183: */
184: public void authorization(String value) {
185: if (value != null) {
186: put("authorization", value);
187: } else {
188: remove("authorization");
189: }
190: }
191:
192: /** Get the cache control directives that must be obeyed.
193: */
194: public String cacheControl() {
195: return getProperty("cache-control");
196: }
197:
198: /** Set the cache control directives that must be obeyed.
199: */
200: public void cacheControl(String value) {
201: put("cache-control", value);
202: }
203:
204: /** Get sender connection options.
205: */
206: public String connection() {
207: return getProperty("connection");
208: }
209:
210: /** Set sender connection options.
211: */
212: public void connection(String value) {
213: put("connection", value);
214: }
215:
216: /** See if the resource context contains a value for a given key. Keys are case insensitive.
217: * @param keyi the name of the value to check for
218: * @return true if the context contains a value for the key
219: * @exception IllegalArgumentException thrown if keyi is not a String
220: */
221: public boolean containsKey(Object keyi)
222: throws IllegalArgumentException {
223: String key = null;
224:
225: if (keyi instanceof String) {
226: key = ((String) keyi).toLowerCase();
227: } else {
228: throw new IllegalArgumentException(
229: "internal programming error: header must be string: "
230: + keyi);
231: }
232:
233: return super .containsKey(key);
234: }
235:
236: /** Get what additional content encodings have been applied to the entity body.
237: */
238: public String contentEncoding() {
239: return getProperty("content-encoding");
240: }
241:
242: /** Set what additional content encodings have been applied to the entity body.
243: */
244: public void contentEncoding(String value) {
245: put("content-encoding", value);
246: }
247:
248: /** Get the natural language of the intended audience for the entity body.
249: */
250: public String contentLanguage() {
251: return getProperty("content-language");
252: }
253:
254: /** Set the natural language of the intended audience for the entity body.
255: */
256: public void contentLanguage(String value) {
257: put("content-language", value);
258: }
259:
260: /** Get the content length in bytes of the entity body.
261: */
262: public long contentLength() {
263: return Long.parseLong(getProperty("content-length", "-1"));
264: }
265:
266: /** Set the content length in bytes of the entity body.
267: */
268: public void contentLength(long value) {
269: put("content-length", (new Long(value)).toString());
270: }
271:
272: /** Get the resource location for the response.
273: */
274: public String contentLocation() {
275: return getProperty("content-location");
276: }
277:
278: /** Set the resource location for the response.
279: */
280: public void contentLocation(String value) {
281: put("content-location", value);
282: }
283:
284: /** Get the MIME type for the response contents.
285: * @return the Content-Type header
286: */
287: public String contentType() {
288: return getProperty("content-type");
289: }
290:
291: /** Set the MIME type for the response contents.
292: * @param value the MIME Content-Type
293: */
294: public void contentType(String value) {
295: put("content-type", value);
296: }
297:
298: /** The date the request was made.
299: * @return the Date header
300: */
301: public String date() {
302: return getProperty("date");
303: }
304:
305: /** Set the date the request was made.
306: */
307: public void date(String value) {
308: put("date", value);
309: }
310:
311: /** Get the DAV level supported by the server.
312: */
313: public String DAV() {
314: return getProperty("dav");
315: }
316:
317: /** Set the DAV level supported by the server.
318: */
319: public void DAV(String value) {
320: put("dav", value);
321: }
322:
323: /** Get the depth to apply to resource collections.
324: */
325: public String depth() {
326: return getProperty("depth");
327: }
328:
329: /** Set the depth to be applied to resource collections.
330: */
331: public void depth(String value) {
332: put("depth", value);
333: }
334:
335: /** Get the destination URL for a copy or move operation.
336: */
337: public String destination() {
338: return getProperty("destination");
339: }
340:
341: /** Set the destination URL for a copy or move operation.
342: */
343: public void destination(String value) {
344: put("destination", value);
345: }
346:
347: /** Get the entity tag for the associated entity.
348: */
349: public String etag() {
350: return getProperty("etag");
351: }
352:
353: /** Set the entity tag for the associated entity.
354: */
355: public void etag(String value) {
356: put("etag", value);
357: }
358:
359: /** Get the date/time after which the response should be considered stale.
360: */
361: public String expires() {
362: return getProperty("expires");
363: }
364:
365: /** Set the date/time after which the response should be considered stale.
366: */
367: public void expires(String value) {
368: put("expires", value);
369: }
370:
371: /** Get the value of an entry in the resource context. Keys are case insensitive.
372: * @param keyi the name of the value to get
373: * @exception IllegalArgumentException thrown if keyi is not a String
374: */
375: public Object get(Object keyi) {
376: String key = null;
377:
378: if (keyi instanceof String) {
379: key = ((String) keyi).toLowerCase();
380: } else {
381: throw new IllegalArgumentException(
382: "internal programming error: header must be string: "
383: + keyi);
384: }
385:
386: return super .get(key);
387: }
388:
389: /** Get the user agent or principal's identifier from the authorication context.
390: * @return the user agent's identifier
391: */
392: public String getAuthorizationId() {
393: if (authorization() == null) {
394: return null;
395: }
396:
397: String authorization = authorization().trim();
398: String id = null;
399:
400: if (authorization.startsWith("Basic")
401: || authorization.startsWith("BASIC")) {
402: String basicCookie = authorization.substring(6);
403:
404: try {
405: id = new String(base64decoder.decodeBuffer(basicCookie));
406: } catch (IOException exc) {
407: }
408:
409: int colon = id.indexOf(':');
410:
411: if (colon > 0) {
412: id = id.substring(0, colon);
413: }
414: }
415:
416: return id;
417: }
418:
419: /** Get the user agent or principal's password from the authorication context.
420: * @return the user agent's password
421: */
422: public String getPassword() {
423: if (authorization() == null) {
424: return null;
425: }
426:
427: String authorization = authorization().trim();
428: String pw = null;
429:
430: if (authorization.startsWith("Basic")
431: || authorization.startsWith("BASIC")) {
432: String basicCookie = authorization.substring(6);
433:
434: try {
435: pw = new String(base64decoder.decodeBuffer(basicCookie));
436: } catch (IOException exc) {
437: }
438:
439: int colon = pw.indexOf(':');
440:
441: if (colon > 0) {
442: pw = pw.substring(colon + 1);
443: }
444: }
445:
446: return pw;
447: }
448:
449: /** Get the lock timeout value. The lock is a candidate for timeing out
450: * after this nunber of seconds has elapsed.
451: *
452: * @return the lock timeout value in seconds. -1 means infinite timeout.
453: */
454: public int getTimeout() {
455: String t = timeout();
456: int timeout = -1;
457:
458: if ((t == null) || t.equals("Infinity")) {
459: timeout = -1;
460: } else if (t.startsWith("Second-")) {
461: timeout = new Integer(t.substring(7)).intValue();
462: }
463:
464: // ignore all other cases, and use inifite timeout
465: return timeout;
466: }
467:
468: /** Get the Internet host and port of the resource being requested.
469: */
470: public String host() {
471: return getProperty("host");
472: }
473:
474: /** Set the Internet host and port of the resource being requested.
475: */
476: public void host(String value) {
477: put("host", value);
478: }
479:
480: /** Get when the resource was last modified.
481: */
482: public String lastModified() {
483: return getProperty("last-modified");
484: }
485:
486: /** Set when the resource was last modified.
487: */
488: public void lastModified(String value) {
489: put("last-modified", value);
490: }
491:
492: /** Get the redirect location.
493: */
494: public String location() {
495: return getProperty("location");
496: }
497:
498: /** Set the redirect location.
499: */
500: public void location(String value) {
501: put("location", value);
502: }
503:
504: /** Get the lock token for the resource.
505: * @return the lock token (not the coded URL returned in the HTTP Lock-Token header)
506: */
507: public String lockToken() {
508: String lockToken = getProperty("lock-token");
509:
510: if (lockToken.charAt(0) == '<') {
511: lockToken = lockToken.substring(1, lockToken.length() - 1);
512: }
513:
514: return lockToken;
515: }
516:
517: /** Set the lock token for the resource. This context item must be set
518: * before invoking any method on a locked resource that changes the state
519: * of the resource.
520: * @param value the locktoken (not the coded URL in the HTTP Lock-Token header)
521: */
522: public void lockToken(String value) {
523: // convert the lock token to an HTTP Lock-Token header
524: put("lock-token", "<" + value + ">");
525: }
526:
527: /** Get if copy or move should overwrite an existing destination.
528: * @return "T" if overwrite is true
529: */
530: public String overwrite() {
531: return getProperty("overwrite");
532: }
533:
534: /** Set if copy or move should overwrite an existing destination.
535: * @param value "T" if overwrite is true, "F" for false
536: */
537: public void overwrite(String value) {
538: put("overwrite", value);
539: }
540:
541: /** Get any precondition that must be true in order for method
542: * execution to be successful. A precondition corresponds to the
543: * WebDAV "If" header.
544: */
545: public Precondition precondition() throws WebDAVException {
546: String ifHeader = getProperty("if");
547: Precondition precondition = null;
548:
549: if (ifHeader != null) {
550: precondition = new Precondition(ifHeader);
551: }
552:
553: return precondition;
554: }
555:
556: /** Set any precondition that must be true in order for method
557: * execution to be successful. A precondition corresponds to the
558: * WebDAV "If" header.
559: */
560: public void precondition(Precondition value) {
561: if (value != null) {
562: put("if", value.toString());
563: } else {
564: remove("if");
565: }
566: }
567:
568: /** Set any precondition that must be true in order for method
569: * execution to be successful. A precondition corresponds to the
570: * WebDAV "If" header.
571: */
572: public void precondition(String value) {
573: if (value != null) {
574: put("if", value);
575: } else {
576: remove("if");
577: }
578: }
579:
580: /** Set the value of a resource context. Keys are case insensitive.
581: * @param keyi the name of the value
582: * @param value the value to set
583: */
584: public Object put(Object keyi, Object value) {
585: String key = null;
586:
587: if (keyi instanceof String) {
588: key = ((String) keyi).toLowerCase();
589: } else {
590: throw new IllegalArgumentException(
591: "internal programming error: header must be string: "
592: + keyi);
593: }
594:
595: return super .put(key, value);
596: }
597:
598: /** Get the URI of the resource from which the request was obtained.
599: */
600: public String referer() {
601: return getProperty("referer");
602: }
603:
604: /** Set the URI of the resource from which the request was obtained.
605: */
606: public void referer(String value) {
607: put("referer", value);
608: }
609:
610: /** Remove an entry from the resource context. Keys are case insensitive.
611: * @param keyi the name of the entry to remove
612: * @return the object removed
613: */
614: public Object remove(Object keyi) {
615: String key = null;
616:
617: if (keyi instanceof String) {
618: key = ((String) keyi).toLowerCase();
619: } else {
620: throw new IllegalArgumentException(
621: "internal programming error: header must be string: "
622: + keyi);
623: }
624:
625: return super .remove(key);
626: }
627:
628: /** Get information about the software used by the origin server
629: * to handle the request.
630: */
631: public String server() {
632: return getProperty("server");
633: }
634:
635: /** Set information about the software used by the origin server
636: * to handle the request.
637: */
638: public void server(String value) {
639: put("server", value);
640: }
641:
642: /** Set the authorization context using the Basic authentication scheme.
643: * @param userid the authorization id of the user agent or principal
644: * @param password the user agent's password
645: */
646: public void setBasicAuthorization(String userid, String password) {
647: String authString = base64encoder
648: .encode((userid + ":" + password).getBytes());
649: authorization("Basic " + authString);
650: }
651:
652: /** Set the lock timeout value. The lock is a candidate for timeing out
653: * after this nunber of seconds has elapsed.
654: *
655: * @param value the lock timeout value in seconds. -1 means infinite timeout.
656: */
657: public void setTimeout(int value) {
658: if (value == -1) {
659: timeout("Infinity");
660: } else {
661: timeout("Second-" + value);
662: }
663: }
664:
665: /** Get the URI of the resource whose method is in process.
666: */
667: public String statusURI() {
668: return getProperty("status-uri");
669: }
670:
671: /** Set the URI of the resource whose method is in process.
672: */
673: public void statusURI(String value) {
674: put("status-uri", value);
675: }
676:
677: /** Get the lock timeout value.
678: */
679: public String timeout() {
680: return getProperty("timeout");
681: }
682:
683: /** Set the lock timeout value.
684: */
685: public void timeout(String value) {
686: put("timeout", value);
687: }
688:
689: /** Get information about the user agent originating the request.
690: */
691: public String userAgent() {
692: return getProperty("user-agent");
693: }
694:
695: /** Set information about the user agent originating the request.
696: */
697: public void userAgent(String value) {
698: put("user-agent", value);
699: }
700: }
|