2 ;;;; Copyright (c) 2008 Zachary Beane, All Rights Reserved
4 ;;;; Redistribution and use in source and binary forms, with or without
5 ;;;; modification, are permitted provided that the following conditions
8 ;;;; * Redistributions of source code must retain the above copyright
9 ;;;; notice, this list of conditions and the following disclaimer.
11 ;;;; * Redistributions in binary form must reproduce the above
12 ;;;; copyright notice, this list of conditions and the following
13 ;;;; disclaimer in the documentation and/or other materials
14 ;;;; provided with the distribution.
16 ;;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
17 ;;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 ;;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ;;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 ;;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 ;;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 ;;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 ;;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 ;;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 ;;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 ;;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 ;;;; bucket-listing.lisp
32 (defbinder all-buckets
33 ("ListAllMyBucketsResult"
35 ("ID" (bind :owner-id
))
36 ("DisplayName" (bind :display-name
)))
41 ("CreationDate" (bind :creation-date
)))))))
43 (defclass all-buckets
(response)
51 (set-element-class "ListAllMyBucketsResult" 'all-buckets
)
53 (defmethod specialized-initialize ((response all-buckets
) source
)
54 (let ((bindings (xml-bind 'all-buckets source
)))
55 (setf (owner response
)
56 (make-instance 'person
57 :id
(bvalue :owner-id bindings
)
58 :display-name
(bvalue :display-name bindings
)))
59 (let* ((bucket-bindings (bvalue :buckets bindings
))
60 (buckets (make-array (length bucket-bindings
))))
61 (setf (buckets response
) buckets
)
63 for
((nil . name
) (nil . timestamp
)) in bucket-bindings
64 do
(setf (aref buckets i
)
65 (make-instance 'bucket
67 :creation-date
(parse-amazon-timestamp timestamp
)))))))
70 (defbinder list-bucket-result
72 ("Name" (bind :bucket-name
))
73 ("Prefix" (bind :prefix
))
74 ("Marker" (bind :marker
))
76 ("NextMarker" (bind :next-marker
)))
77 ("MaxKeys" (bind :max-keys
))
79 ("Delimiter" (bind :delimiter
)))
80 ("IsTruncated" (bind :truncatedp
))
84 ("LastModified" (bind :last-modified
))
89 ("ID" (bind :owner-id
))
90 ("DisplayName" (bind :owner-display-name
))))
91 ("StorageClass" (bind :storage-class
))))
92 (sequence :common-prefixes
94 ("Prefix" (bind :prefix
))))))
96 (defclass bucket-listing
(response)
99 :accessor bucket-name
)
107 :initarg
:next-marker
108 :accessor next-marker
)
117 :accessor truncatedp
)
122 :initarg
:common-prefixes
123 :accessor common-prefixes
))
130 (defmethod print-object ((response bucket-listing
) stream
)
131 (print-unreadable-object (response stream
:type t
)
132 (format stream
"~S~@[ (truncated)~]"
133 (bucket-name response
)
134 (truncatedp response
))))
137 (set-element-class "ListBucketResult" 'bucket-listing
)
139 (defun key-binding-key (binding)
141 last-modified etag size
142 owner-id owner-display-name
147 :last-modified
(parse-amazon-timestamp last-modified
)
149 :size
(parse-integer size
)
150 :owner
(when owner-id
151 (make-instance 'person
153 :display-name owner-display-name
))
154 :storage-class storage-class
)))
156 (defmethod specialized-initialize ((response bucket-listing
) source
)
157 (let* ((bindings (xml-bind 'list-bucket-result source
))
158 (bucket-name (bvalue :bucket-name bindings
)))
159 (setf (bucket-name response
) bucket-name
)
160 (setf (prefix response
) (bvalue :prefix bindings
))
161 (setf (marker response
) (bvalue :marker bindings
))
162 (setf (next-marker response
) (bvalue :next-marker bindings
))
163 (setf (max-keys response
) (parse-integer (bvalue :max-keys bindings
)))
164 (setf (delimiter response
) (bvalue :delimiter bindings
))
165 (setf (truncatedp response
) (equal (bvalue :truncatedp bindings
)
167 (setf (keys response
)
169 (lambda (key-binding)
170 (key-binding-key key-binding
))
171 (bvalue :keys bindings
)))
172 (setf (common-prefixes response
)
173 (map 'vector
#'cdar
(bvalue :common-prefixes bindings
)))))
175 (defgeneric successive-marker
(response)
176 (:method
((response bucket-listing
))
177 (when (truncatedp response
)
178 (let* ((k1 (next-marker response
))
179 (k2 (last-entry (keys response
)))
180 (k3 (last-entry (common-prefixes response
))))
182 ((and k2
(not k3
)) (name k2
))
184 ((string< (name k3
) (name k2
)) (name k2
))
187 (defgeneric successive-request
(response)
188 (:method
((response bucket-listing
))
189 (when (truncatedp response
)
190 (make-instance 'request
191 :credentials
(credentials (request response
))
193 :bucket
(bucket-name response
)
195 (parameters-alist :max-keys
(max-keys response
)
196 :delimiter
(delimiter response
)
197 :marker
(successive-marker response
)
198 :prefix
(prefix response
))))))