View Javadoc

1   /**
2    *
3    * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
4    *
5    * ====================================================================
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   * ====================================================================
18   */
19  package org.jclouds.blobstore.options;
20  
21  import static com.google.common.base.Preconditions.checkArgument;
22  import static com.google.common.base.Preconditions.checkNotNull;
23  
24  import java.io.UnsupportedEncodingException;
25  import java.util.ArrayList;
26  import java.util.Date;
27  import java.util.List;
28  
29  /**
30   * Contains options supported for HTTP GET operations. <h2>
31   * Usage</h2> The recommended way to instantiate a {@link GetOptions} object is to statically import
32   * GetOptions.Builder.* and invoke a static creation method followed by an instance mutator (if
33   * needed):
34   * <p/>
35   * <code>
36   * import static org.jclouds.blobstore.options.GetOptions.Builder.*
37   * 
38   * 
39   * // this will get the first megabyte of an blob, provided it wasn't modified since yesterday
40   * blob = blobStore.getBlob("container, "blobName",range(0,1024).ifUnmodifiedSince(new Date().minusDays(1)));
41   * <code>
42   * 
43   * @author Adrian Cole
44   * 
45   */
46  public class GetOptions {
47  
48     public static final GetOptions NONE = new GetOptions();
49  
50     private final List<String> ranges = new ArrayList<String>();
51     private Date ifModifiedSince;
52     private Date ifUnmodifiedSince;
53     private String ifMatch;
54     private String ifNoneMatch;
55  
56     /**
57      * download the specified range of the object.
58      */
59     public GetOptions range(long start, long end) {
60        checkArgument(start >= 0, "start must be >= 0");
61        checkArgument(end >= 0, "end must be >= 0");
62        getRanges().add(String.format("%d-%d", start, end));
63        return this;
64     }
65  
66     /**
67      * download the specified range of the object.
68      */
69     public GetOptions startAt(long start) {
70        checkArgument(start >= 0, "start must be >= 0");
71        getRanges().add(String.format("%d-", start));
72        return this;
73     }
74  
75     /**
76      * Only return the object if it has changed since this time.
77      * <p />
78      * Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)}
79      */
80     public GetOptions ifModifiedSince(Date ifModifiedSince) {
81        checkArgument(getIfMatch() == null, "ifETagMatches() is not compatible with ifModifiedSince()");
82        checkArgument(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifModifiedSince()");
83        this.ifModifiedSince = checkNotNull(ifModifiedSince, "ifModifiedSince");
84        return this;
85     }
86  
87     /**
88      * For use in the header If-Modified-Since
89      * <p />
90      * Return the object only if it has been modified since the specified time, otherwise return a
91      * 304 (not modified).
92      * 
93      * @see GetOptions#ifModifiedSince(Date)
94      */
95     public Date getIfModifiedSince() {
96        return this.ifModifiedSince;
97     }
98  
99     /**
100     * Only return the object if it hasn't changed since this time.
101     * <p />
102     * Not compatible with {@link #ifETagDoesntMatch(String)} or {@link #ifModifiedSince(Date)}
103     */
104    public GetOptions ifUnmodifiedSince(Date ifUnmodifiedSince) {
105       checkArgument(getIfNoneMatch() == null, "ifETagDoesntMatch() is not compatible with ifUnmodifiedSince()");
106       checkArgument(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifUnmodifiedSince()");
107       this.ifUnmodifiedSince = checkNotNull(ifUnmodifiedSince, "ifUnmodifiedSince");
108       return this;
109    }
110 
111    /**
112     * For use in the header If-Unmodified-Since
113     * <p />
114     * Return the object only if it has not been modified since the specified time, otherwise return
115     * a 412 (precondition failed).
116     * 
117     * @see GetOptions#ifUnmodifiedSince(Date)
118     */
119    public Date getIfUnmodifiedSince() {
120       return this.ifUnmodifiedSince;
121    }
122 
123    /**
124     * The object's eTag hash should match the parameter <code>eTag</code>.
125     * 
126     * <p />
127     * Not compatible with {@link #ifETagDoesntMatch(String)} or {@link #ifModifiedSince(Date)}
128     * 
129     * @param eTag
130     *           hash representing the payload
131     */
132    public GetOptions ifETagMatches(String eTag) {
133       checkArgument(getIfNoneMatch() == null, "ifETagDoesntMatch() is not compatible with ifETagMatches()");
134       checkArgument(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifETagMatches()");
135       this.ifMatch = checkNotNull(eTag, "eTag");
136       return this;
137    }
138 
139    /**
140     * For use in the request header: If-Match
141     * <p />
142     * Return the object only if its payload tag (ETag) is the same as the eTag specified, otherwise
143     * return a 412 (precondition failed).
144     * 
145     * @see GetOptions#ifETagMatches(String)
146     */
147    public String getIfMatch() {
148       return this.ifMatch;
149    }
150 
151    /**
152     * The object should not have a eTag hash corresponding with the parameter <code>eTag</code>.
153     * <p />
154     * Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)}
155     * 
156     * @param eTag
157     *           hash representing the payload
158     */
159    public GetOptions ifETagDoesntMatch(String eTag) {
160       checkArgument(getIfMatch() == null, "ifETagMatches() is not compatible with ifETagDoesntMatch()");
161       checkArgument(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifETagDoesntMatch()");
162       this.ifNoneMatch = checkNotNull(eTag, "eTag");
163       return this;
164    }
165 
166    /**
167     * For use in the request header: If-None-Match
168     * <p />
169     * Return the object only if its payload tag (ETag) is different from the one specified,
170     * otherwise return a 304 (not modified).
171     * 
172     * @see GetOptions#ifETagDoesntMatch(String)
173     */
174    public String getIfNoneMatch() {
175       return this.ifNoneMatch;
176    }
177 
178    public List<String> getRanges() {
179       return ranges;
180    }
181 
182    public static class Builder {
183 
184       /**
185        * @see GetOptions#range(long, long)
186        */
187       public static GetOptions range(long start, long end) {
188          GetOptions options = new GetOptions();
189          return options.range(start, end);
190       }
191 
192       /**
193        * @see GetOptions#getIfModifiedSince()
194        */
195       public static GetOptions ifModifiedSince(Date ifModifiedSince) {
196          GetOptions options = new GetOptions();
197          return options.ifModifiedSince(ifModifiedSince);
198       }
199 
200       /**
201        * @see GetOptions#ifUnmodifiedSince(Date)
202        */
203       public static GetOptions ifUnmodifiedSince(Date ifUnmodifiedSince) {
204          GetOptions options = new GetOptions();
205          return options.ifUnmodifiedSince(ifUnmodifiedSince);
206       }
207 
208       /**
209        * @see GetOptions#ifETagMatches(String)
210        */
211       public static GetOptions ifETagMatches(String eTag) throws UnsupportedEncodingException {
212          GetOptions options = new GetOptions();
213          return options.ifETagMatches(eTag);
214       }
215 
216       /**
217        * @see GetOptions#ifETagDoesntMatch(String)
218        */
219       public static GetOptions ifETagDoesntMatch(String eTag) throws UnsupportedEncodingException {
220          GetOptions options = new GetOptions();
221          return options.ifETagDoesntMatch(eTag);
222       }
223 
224    }
225 
226    @Override
227    public int hashCode() {
228       final int prime = 31;
229       int result = 1;
230       result = prime * result + ((ifMatch == null) ? 0 : ifMatch.hashCode());
231       result = prime * result + ((ifModifiedSince == null) ? 0 : ifModifiedSince.hashCode());
232       result = prime * result + ((ifNoneMatch == null) ? 0 : ifNoneMatch.hashCode());
233       result = prime * result + ((ifUnmodifiedSince == null) ? 0 : ifUnmodifiedSince.hashCode());
234       result = prime * result + ((ranges == null) ? 0 : ranges.hashCode());
235       return result;
236    }
237 
238    @Override
239    public boolean equals(Object obj) {
240       if (this == obj)
241          return true;
242       if (obj == null)
243          return false;
244       if (getClass() != obj.getClass())
245          return false;
246       GetOptions other = (GetOptions) obj;
247       if (ifMatch == null) {
248          if (other.ifMatch != null)
249             return false;
250       } else if (!ifMatch.equals(other.ifMatch))
251          return false;
252       if (ifModifiedSince == null) {
253          if (other.ifModifiedSince != null)
254             return false;
255       } else if (!ifModifiedSince.equals(other.ifModifiedSince))
256          return false;
257       if (ifNoneMatch == null) {
258          if (other.ifNoneMatch != null)
259             return false;
260       } else if (!ifNoneMatch.equals(other.ifNoneMatch))
261          return false;
262       if (ifUnmodifiedSince == null) {
263          if (other.ifUnmodifiedSince != null)
264             return false;
265       } else if (!ifUnmodifiedSince.equals(other.ifUnmodifiedSince))
266          return false;
267       if (ranges == null) {
268          if (other.ranges != null)
269             return false;
270       } else if (!ranges.equals(other.ranges))
271          return false;
272       return true;
273    }
274 
275    @Override
276    public String toString() {
277       return "[ranges=" + ranges + ", ifModifiedSince=" + ifModifiedSince + ", ifUnmodifiedSince=" + ifUnmodifiedSince
278                + ", ifMatch=" + ifMatch + ", ifNoneMatch=" + ifNoneMatch + "]";
279    }
280 
281 }