001: package com.flexive.war.webdav.catalina;
002:
003: import javax.naming.NamingEnumeration;
004: import javax.naming.NamingException;
005: import javax.naming.directory.Attribute;
006: import javax.naming.directory.Attributes;
007: import javax.naming.directory.BasicAttribute;
008: import java.text.ParseException;
009: import java.text.SimpleDateFormat;
010: import java.util.Date;
011: import java.util.Locale;
012: import java.util.TimeZone;
013: import java.util.Vector;
014:
015: /**
016: * Catalina sources cloned for packaging issues to the flexive source tree.
017: * Refactored to JDK 1.5 compatibility.
018: * Licensed under the Apache License, Version 2.0
019: * <p/>
020: * Attributes implementation.
021: *
022: * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
023: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
024: */
025: public class ResourceAttributes implements Attributes {
026:
027: // -------------------------------------------------------------- Constants
028:
029: // Default attribute names
030:
031: /**
032: * Creation date.
033: */
034: public static final String CREATION_DATE = "creationdate";
035:
036: /**
037: * Creation date.
038: */
039: public static final String ALTERNATE_CREATION_DATE = "creation-date";
040:
041: /**
042: * Last modification date.
043: */
044: public static final String LAST_MODIFIED = "getlastmodified";
045:
046: /**
047: * Last modification date.
048: */
049: public static final String ALTERNATE_LAST_MODIFIED = "last-modified";
050:
051: /**
052: * Name.
053: */
054: public static final String NAME = "displayname";
055:
056: /**
057: * Type.
058: */
059: public static final String TYPE = "resourcetype";
060:
061: /**
062: * Type.
063: */
064: public static final String ALTERNATE_TYPE = "content-type";
065:
066: /**
067: * Source.
068: */
069: public static final String SOURCE = "source";
070:
071: /**
072: * MIME type of the content.
073: */
074: public static final String CONTENT_TYPE = "getcontenttype";
075:
076: /**
077: * Content language.
078: */
079: public static final String CONTENT_LANGUAGE = "getcontentlanguage";
080:
081: /**
082: * Content length.
083: */
084: public static final String CONTENT_LENGTH = "getcontentlength";
085:
086: /**
087: * Content length.
088: */
089: public static final String ALTERNATE_CONTENT_LENGTH = "content-length";
090:
091: /**
092: * ETag.
093: */
094: public static final String ETAG = "getetag";
095:
096: /**
097: * Collection type.
098: */
099: public static final String COLLECTION_TYPE = "<collection/>";
100:
101: /**
102: * HTTP date format.
103: */
104: protected static final SimpleDateFormat format = new SimpleDateFormat(
105: "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
106:
107: /**
108: * Date formats using for Date parsing.
109: */
110: protected static final SimpleDateFormat formats[] = {
111: new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz",
112: Locale.US),
113: new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz",
114: Locale.US),
115: new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
116:
117: protected final static TimeZone gmtZone = TimeZone
118: .getTimeZone("GMT");
119:
120: /**
121: * GMT timezone - all HTTP dates are on GMT
122: */
123: static {
124:
125: format.setTimeZone(gmtZone);
126:
127: formats[0].setTimeZone(gmtZone);
128: formats[1].setTimeZone(gmtZone);
129: formats[2].setTimeZone(gmtZone);
130:
131: }
132:
133: // ----------------------------------------------------------- Constructors
134:
135: /**
136: * Default constructor.
137: */
138: public ResourceAttributes() {
139: }
140:
141: /**
142: * Merges with another attribute set.
143: */
144: public ResourceAttributes(Attributes attributes) {
145: this .attributes = attributes;
146: }
147:
148: // ----------------------------------------------------- Instance Variables
149:
150: /**
151: * Collection flag.
152: */
153: protected boolean collection = false;
154:
155: /**
156: * Content length.
157: */
158: protected long contentLength = -1;
159:
160: /**
161: * Creation time.
162: */
163: protected long creation = -1;
164:
165: /**
166: * Creation date.
167: */
168: protected Date creationDate = null;
169:
170: /**
171: * Last modified time.
172: */
173: protected long lastModified = -1;
174:
175: /**
176: * Last modified date.
177: */
178: protected Date lastModifiedDate = null;
179:
180: /**
181: * Last modified date in HTTP format.
182: */
183: protected String lastModifiedHttp = null;
184:
185: /**
186: * MIME type.
187: */
188: protected String mimeType = null;
189:
190: /**
191: * Name.
192: */
193: protected String name = null;
194:
195: /**
196: * Weak ETag.
197: */
198: protected String weakETag = null;
199:
200: /**
201: * Strong ETag.
202: */
203: protected String strongETag = null;
204:
205: /**
206: * External attributes.
207: */
208: protected Attributes attributes = null;
209:
210: // ------------------------------------------------------------- Properties
211:
212: /**
213: * Is collection.
214: */
215: public boolean isCollection() {
216: if (attributes != null) {
217: return (getResourceType().equals(COLLECTION_TYPE));
218: } else {
219: return (collection);
220: }
221: }
222:
223: /**
224: * Set collection flag.
225: *
226: * @param collection New flag value
227: */
228: public void setCollection(boolean collection) {
229: this .collection = collection;
230: if (attributes != null) {
231: String value = "";
232: if (collection)
233: value = COLLECTION_TYPE;
234: attributes.put(TYPE, value);
235: }
236: }
237:
238: /**
239: * Get content length.
240: *
241: * @return content length value
242: */
243: public long getContentLength() {
244: if (contentLength != -1L)
245: return contentLength;
246: if (attributes != null) {
247: Attribute attribute = attributes.get(CONTENT_LENGTH);
248: if (attribute != null) {
249: try {
250: Object value = attribute.get();
251: if (value instanceof Long) {
252: contentLength = (Long) value;
253: } else {
254: try {
255: contentLength = Long.parseLong(value
256: .toString());
257: } catch (NumberFormatException e) {
258: // Ignore
259: }
260: }
261: } catch (NamingException e) {
262: // No value for the attribute
263: }
264: }
265: }
266: return contentLength;
267: }
268:
269: /**
270: * Set content length.
271: *
272: * @param contentLength New content length value
273: */
274: public void setContentLength(long contentLength) {
275: this .contentLength = contentLength;
276: if (attributes != null)
277: attributes.put(CONTENT_LENGTH, contentLength);
278: }
279:
280: /**
281: * Get creation time.
282: *
283: * @return creation time value
284: */
285: public long getCreation() {
286: if (creation != -1L)
287: return creation;
288: if (creationDate != null)
289: return creationDate.getTime();
290: if (attributes != null) {
291: Attribute attribute = attributes.get(CREATION_DATE);
292: if (attribute != null) {
293: try {
294: Object value = attribute.get();
295: if (value instanceof Long) {
296: creation = (Long) value;
297: } else if (value instanceof Date) {
298: creation = ((Date) value).getTime();
299: creationDate = (Date) value;
300: } else {
301: String creationDateValue = value.toString();
302: Date result = null;
303: // Parsing the HTTP Date
304: for (int i = 0; (result == null)
305: && (i < formats.length); i++) {
306: try {
307: result = formats[i]
308: .parse(creationDateValue);
309: } catch (ParseException e) {
310: //ignore
311: }
312: }
313: if (result != null) {
314: creation = result.getTime();
315: creationDate = result;
316: }
317: }
318: } catch (NamingException e) {
319: // No value for the attribute
320: }
321: }
322: }
323: return creation;
324: }
325:
326: /**
327: * Set creation.
328: *
329: * @param creation New creation value
330: */
331: public void setCreation(long creation) {
332: this .creation = creation;
333: this .creationDate = null;
334: if (attributes != null)
335: attributes.put(CREATION_DATE, new Date(creation));
336: }
337:
338: /**
339: * Get creation date.
340: *
341: * @return Creation date value
342: */
343: public Date getCreationDate() {
344: if (creationDate != null)
345: return creationDate;
346: if (creation != -1L) {
347: creationDate = new Date(creation);
348: return creationDate;
349: }
350: if (attributes != null) {
351: Attribute attribute = attributes.get(CREATION_DATE);
352: if (attribute != null) {
353: try {
354: Object value = attribute.get();
355: if (value instanceof Long) {
356: creation = (Long) value;
357: creationDate = new Date(creation);
358: } else if (value instanceof Date) {
359: creation = ((Date) value).getTime();
360: creationDate = (Date) value;
361: } else {
362: String creationDateValue = value.toString();
363: Date result = null;
364: // Parsing the HTTP Date
365: for (int i = 0; (result == null)
366: && (i < formats.length); i++) {
367: try {
368: result = formats[i]
369: .parse(creationDateValue);
370: } catch (ParseException e) {
371: //ignore
372: }
373: }
374: if (result != null) {
375: creation = result.getTime();
376: creationDate = result;
377: }
378: }
379: } catch (NamingException e) {
380: // No value for the attribute
381: }
382: }
383: }
384: return creationDate;
385: }
386:
387: /**
388: * Creation date mutator.
389: *
390: * @param creationDate New creation date
391: */
392: public void setCreationDate(Date creationDate) {
393: this .creation = creationDate.getTime();
394: this .creationDate = creationDate;
395: if (attributes != null)
396: attributes.put(CREATION_DATE, creationDate);
397: }
398:
399: /**
400: * Get last modified time.
401: *
402: * @return lastModified time value
403: */
404: public long getLastModified() {
405: if (lastModified != -1L)
406: return lastModified;
407: if (lastModifiedDate != null)
408: return lastModifiedDate.getTime();
409: if (attributes != null) {
410: Attribute attribute = attributes.get(LAST_MODIFIED);
411: if (attribute != null) {
412: try {
413: Object value = attribute.get();
414: if (value instanceof Long) {
415: lastModified = (Long) value;
416: } else if (value instanceof Date) {
417: lastModified = ((Date) value).getTime();
418: lastModifiedDate = (Date) value;
419: } else {
420: String lastModifiedDateValue = value.toString();
421: Date result = null;
422: // Parsing the HTTP Date
423: for (int i = 0; (result == null)
424: && (i < formats.length); i++) {
425: try {
426: result = formats[i]
427: .parse(lastModifiedDateValue);
428: } catch (ParseException e) {
429: //ignore
430: }
431: }
432: if (result != null) {
433: lastModified = result.getTime();
434: lastModifiedDate = result;
435: }
436: }
437: } catch (NamingException e) {
438: // No value for the attribute
439: }
440: }
441: }
442: return lastModified;
443: }
444:
445: /**
446: * Set last modified.
447: *
448: * @param lastModified New last modified value
449: */
450: public void setLastModified(long lastModified) {
451: this .lastModified = lastModified;
452: this .lastModifiedDate = null;
453: if (attributes != null)
454: attributes.put(LAST_MODIFIED, new Date(lastModified));
455: }
456:
457: /**
458: * Set last modified date.
459: *
460: * @param lastModified New last modified date value
461: * @deprecated
462: */
463: public void setLastModified(Date lastModified) {
464: setLastModifiedDate(lastModified);
465: }
466:
467: /**
468: * Get lastModified date.
469: *
470: * @return LastModified date value
471: */
472: public Date getLastModifiedDate() {
473: if (lastModifiedDate != null)
474: return lastModifiedDate;
475: if (lastModified != -1L) {
476: lastModifiedDate = new Date(lastModified);
477: return lastModifiedDate;
478: }
479: if (attributes != null) {
480: Attribute attribute = attributes.get(LAST_MODIFIED);
481: if (attribute != null) {
482: try {
483: Object value = attribute.get();
484: if (value instanceof Long) {
485: lastModified = (Long) value;
486: lastModifiedDate = new Date(lastModified);
487: } else if (value instanceof Date) {
488: lastModified = ((Date) value).getTime();
489: lastModifiedDate = (Date) value;
490: } else {
491: String lastModifiedDateValue = value.toString();
492: Date result = null;
493: // Parsing the HTTP Date
494: for (int i = 0; (result == null)
495: && (i < formats.length); i++) {
496: try {
497: result = formats[i]
498: .parse(lastModifiedDateValue);
499: } catch (ParseException e) {
500: //ignore
501: }
502: }
503: if (result != null) {
504: lastModified = result.getTime();
505: lastModifiedDate = result;
506: }
507: }
508: } catch (NamingException e) {
509: // No value for the attribute
510: }
511: }
512: }
513: return lastModifiedDate;
514: }
515:
516: /**
517: * Last modified date mutator.
518: *
519: * @param lastModifiedDate New last modified date
520: */
521: public void setLastModifiedDate(Date lastModifiedDate) {
522: this .lastModified = lastModifiedDate.getTime();
523: this .lastModifiedDate = lastModifiedDate;
524: if (attributes != null)
525: attributes.put(LAST_MODIFIED, lastModifiedDate);
526: }
527:
528: /**
529: * @return Returns the lastModifiedHttp.
530: */
531: public String getLastModifiedHttp() {
532: if (lastModifiedHttp != null)
533: return lastModifiedHttp;
534: Date modifiedDate = getLastModifiedDate();
535: if (modifiedDate == null) {
536: modifiedDate = getCreationDate();
537: }
538: if (modifiedDate == null) {
539: modifiedDate = new Date();
540: }
541: synchronized (format) {
542: lastModifiedHttp = format.format(modifiedDate);
543: }
544: return lastModifiedHttp;
545: }
546:
547: /**
548: * @param lastModifiedHttp The lastModifiedHttp to set.
549: */
550: public void setLastModifiedHttp(String lastModifiedHttp) {
551: this .lastModifiedHttp = lastModifiedHttp;
552: }
553:
554: /**
555: * @return Returns the mimeType.
556: */
557: public String getMimeType() {
558: return mimeType;
559: }
560:
561: /**
562: * @param mimeType The mimeType to set.
563: */
564: public void setMimeType(String mimeType) {
565: this .mimeType = mimeType;
566: }
567:
568: /**
569: * Get name.
570: *
571: * @return Name value
572: */
573: public String getName() {
574: if (name != null)
575: return name;
576: if (attributes != null) {
577: Attribute attribute = attributes.get(NAME);
578: if (attribute != null) {
579: try {
580: name = attribute.get().toString();
581: } catch (NamingException e) {
582: // No value for the attribute
583: }
584: }
585: }
586: return name;
587: }
588:
589: /**
590: * Set name.
591: *
592: * @param name New name value
593: */
594: public void setName(String name) {
595: this .name = name;
596: if (attributes != null)
597: attributes.put(NAME, name);
598: }
599:
600: /**
601: * Get resource type.
602: *
603: * @return String resource type
604: */
605: public String getResourceType() {
606: String result = null;
607: if (attributes != null) {
608: Attribute attribute = attributes.get(TYPE);
609: if (attribute != null) {
610: try {
611: result = attribute.get().toString();
612: } catch (NamingException e) {
613: // No value for the attribute
614: }
615: }
616: }
617: if (result == null) {
618: if (collection)
619: result = COLLECTION_TYPE;
620: else
621: result = "";
622: }
623: return result;
624: }
625:
626: /**
627: * Type mutator.
628: *
629: * @param resourceType New resource type
630: */
631: public void setResourceType(String resourceType) {
632: collection = resourceType.equals(COLLECTION_TYPE);
633: if (attributes != null)
634: attributes.put(TYPE, resourceType);
635: }
636:
637: /**
638: * Get ETag.
639: *
640: * @return Weak ETag
641: */
642: public String getETag() {
643: return getETag(false);
644: }
645:
646: /**
647: * Get ETag.
648: *
649: * @param strong If true, the strong ETag will be returned
650: * @return ETag
651: */
652: public String getETag(boolean strong) {
653: String result;
654: /*if (attributes != null) {
655: Attribute attribute = attributes.get(ETAG);
656: if (attribute != null) {
657: try {
658: result = attribute.get().toString();
659: } catch (NamingException e) {
660: // No value for the attribute
661: }
662: }
663: }*/
664: if (strong) {
665: // The strong ETag must always be calculated by the resources
666: result = strongETag;
667: } else {
668: // The weakETag is contentLenght + lastModified
669: if (weakETag == null) {
670: weakETag = "W/\"" + getContentLength() + "-"
671: + getLastModified() + "\"";
672: }
673: result = weakETag;
674: }
675: return result;
676: }
677:
678: /**
679: * Set strong ETag.
680: */
681: public void setETag(String eTag) {
682: this .strongETag = eTag;
683: if (attributes != null)
684: attributes.put(ETAG, eTag);
685: }
686:
687: /**
688: * Return the canonical path of the resource, to possibly be used for
689: * direct file serving. Implementations which support this should override
690: * it to return the file path.
691: *
692: * @return The canonical path of the resource
693: */
694: public String getCanonicalPath() {
695: return null;
696: }
697:
698: // ----------------------------------------------------- Attributes Methods
699:
700: /**
701: * Get attribute.
702: */
703: public Attribute get(String attrID) {
704: if (attributes == null) {
705: if (attrID.equals(CREATION_DATE)) {
706: return new BasicAttribute(CREATION_DATE,
707: getCreationDate());
708: } else if (attrID.equals(ALTERNATE_CREATION_DATE)) {
709: return new BasicAttribute(ALTERNATE_CREATION_DATE,
710: getCreationDate());
711: } else if (attrID.equals(LAST_MODIFIED)) {
712: return new BasicAttribute(LAST_MODIFIED,
713: getLastModifiedDate());
714: } else if (attrID.equals(ALTERNATE_LAST_MODIFIED)) {
715: return new BasicAttribute(ALTERNATE_LAST_MODIFIED,
716: getLastModifiedDate());
717: } else if (attrID.equals(NAME)) {
718: return new BasicAttribute(NAME, getName());
719: } else if (attrID.equals(TYPE)) {
720: return new BasicAttribute(TYPE, getResourceType());
721: } else if (attrID.equals(ALTERNATE_TYPE)) {
722: return new BasicAttribute(ALTERNATE_TYPE,
723: getResourceType());
724: } else if (attrID.equals(CONTENT_LENGTH)) {
725: return new BasicAttribute(CONTENT_LENGTH,
726: getContentLength());
727: } else if (attrID.equals(ALTERNATE_CONTENT_LENGTH)) {
728: return new BasicAttribute(ALTERNATE_CONTENT_LENGTH,
729: getContentLength());
730: }
731: } else {
732: return attributes.get(attrID);
733: }
734: return null;
735: }
736:
737: /**
738: * Put attribute.
739: */
740: public Attribute put(Attribute attribute) {
741: if (attributes == null) {
742: try {
743: return put(attribute.getID(), attribute.get());
744: } catch (NamingException e) {
745: return null;
746: }
747: } else {
748: return attributes.put(attribute);
749: }
750: }
751:
752: /**
753: * Put attribute.
754: */
755: public Attribute put(String attrID, Object val) {
756: if (attributes == null) {
757: return null; // No reason to implement this
758: } else {
759: return attributes.put(attrID, val);
760: }
761: }
762:
763: /**
764: * Remove attribute.
765: */
766: public Attribute remove(String attrID) {
767: if (attributes == null) {
768: return null; // No reason to implement this
769: } else {
770: return attributes.remove(attrID);
771: }
772: }
773:
774: /**
775: * Get all attributes.
776: */
777: public NamingEnumeration getAll() {
778: if (attributes == null) {
779: Vector<BasicAttribute> attributes = new Vector<BasicAttribute>();
780: attributes.addElement(new BasicAttribute(CREATION_DATE,
781: getCreationDate()));
782: attributes.addElement(new BasicAttribute(LAST_MODIFIED,
783: getLastModifiedDate()));
784: attributes.addElement(new BasicAttribute(NAME, getName()));
785: attributes.addElement(new BasicAttribute(TYPE,
786: getResourceType()));
787: attributes.addElement(new BasicAttribute(CONTENT_LENGTH,
788: getContentLength()));
789: return new RecyclableNamingEnumeration(attributes);
790: } else {
791: return attributes.getAll();
792: }
793: }
794:
795: /**
796: * Get all attribute IDs.
797: */
798: public NamingEnumeration getIDs() {
799: if (attributes == null) {
800: Vector<String> attributeIDs = new Vector<String>();
801: attributeIDs.addElement(CREATION_DATE);
802: attributeIDs.addElement(LAST_MODIFIED);
803: attributeIDs.addElement(NAME);
804: attributeIDs.addElement(TYPE);
805: attributeIDs.addElement(CONTENT_LENGTH);
806: return new RecyclableNamingEnumeration(attributeIDs);
807: } else {
808: return attributes.getIDs();
809: }
810: }
811:
812: /**
813: * Retrieves the number of attributes in the attribute set.
814: */
815: public int size() {
816: if (attributes == null) {
817: return 5;
818: } else {
819: return attributes.size();
820: }
821: }
822:
823: /**
824: * Clone the attributes object (WARNING: fake cloning).
825: */
826: @SuppressWarnings({"CloneDoesntCallSuperClone"})
827: public Object clone() {
828: return this ;
829: }
830:
831: /**
832: * Case sensitivity.
833: */
834: public boolean isCaseIgnored() {
835: return false;
836: }
837:
838: }
|