EMMA Coverage Report (generated Mon Oct 17 05:41:20 EDT 2011)
[all classes][org.jclouds.s3.options]

COVERAGE SUMMARY FOR SOURCE FILE [CopyObjectOptions.java]

nameclass, %method, %block, %line, %
CopyObjectOptions.java100% (2/2)96%  (23/24)96%  (318/332)99%  (59.2/60)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class CopyObjectOptions$Builder100% (1/1)86%  (6/7)94%  (48/51)92%  (12/13)
CopyObjectOptions$Builder (): void 0%   (0/1)0%   (0/3)0%   (0/1)
ifSourceETagDoesntMatch (String): CopyObjectOptions 100% (1/1)100% (8/8)100% (2/2)
ifSourceETagMatches (String): CopyObjectOptions 100% (1/1)100% (8/8)100% (2/2)
ifSourceModifiedSince (Date): CopyObjectOptions 100% (1/1)100% (8/8)100% (2/2)
ifSourceUnmodifiedSince (Date): CopyObjectOptions 100% (1/1)100% (8/8)100% (2/2)
overrideAcl (CannedAccessPolicy): CopyObjectOptions 100% (1/1)100% (8/8)100% (2/2)
overrideMetadataWith (Map): CopyObjectOptions 100% (1/1)100% (8/8)100% (2/2)
     
class CopyObjectOptions100% (1/1)100% (17/17)96%  (270/281)99%  (47.5/48)
buildRequestHeaders (): Multimap 100% (1/1)88%  (83/94)95%  (9.5/10)
<static initializer> 100% (1/1)100% (9/9)100% (2/2)
CopyObjectOptions (): void 100% (1/1)100% (6/6)100% (3/3)
getAcl (): CannedAccessPolicy 100% (1/1)100% (3/3)100% (1/1)
getIfMatch (): String 100% (1/1)100% (4/4)100% (1/1)
getIfModifiedSince (): String 100% (1/1)100% (4/4)100% (1/1)
getIfNoneMatch (): String 100% (1/1)100% (4/4)100% (1/1)
getIfUnmodifiedSince (): String 100% (1/1)100% (4/4)100% (1/1)
getMetadata (): Map 100% (1/1)100% (3/3)100% (1/1)
ifSourceETagDoesntMatch (String): CopyObjectOptions 100% (1/1)100% (31/31)100% (4/4)
ifSourceETagMatches (String): CopyObjectOptions 100% (1/1)100% (31/31)100% (4/4)
ifSourceModifiedSince (Date): CopyObjectOptions 100% (1/1)100% (27/27)100% (4/4)
ifSourceUnmodifiedSince (Date): CopyObjectOptions 100% (1/1)100% (27/27)100% (4/4)
overrideAcl (CannedAccessPolicy): CopyObjectOptions 100% (1/1)100% (17/17)100% (4/4)
overrideMetadataWith (Map): CopyObjectOptions 100% (1/1)100% (9/9)100% (3/3)
setHeaderTag (String): void 100% (1/1)100% (4/4)100% (2/2)
setMetadataPrefix (String): void 100% (1/1)100% (4/4)100% (2/2)

1/**
2 * Licensed to jclouds, Inc. (jclouds) under one or more
3 * contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  jclouds licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  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,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.jclouds.s3.options;
20 
21import static com.google.common.base.Preconditions.checkNotNull;
22import static com.google.common.base.Preconditions.checkState;
23import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
24import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
25import static org.jclouds.s3.reference.S3Headers.CANNED_ACL;
26import static org.jclouds.s3.reference.S3Headers.COPY_SOURCE_IF_MATCH;
27import static org.jclouds.s3.reference.S3Headers.COPY_SOURCE_IF_MODIFIED_SINCE;
28import static org.jclouds.s3.reference.S3Headers.COPY_SOURCE_IF_NO_MATCH;
29import static org.jclouds.s3.reference.S3Headers.COPY_SOURCE_IF_UNMODIFIED_SINCE;
30import static org.jclouds.s3.reference.S3Headers.DEFAULT_AMAZON_HEADERTAG;
31import static org.jclouds.s3.reference.S3Headers.METADATA_DIRECTIVE;
32 
33import java.io.UnsupportedEncodingException;
34import java.util.Date;
35import java.util.Map;
36import java.util.Map.Entry;
37 
38import javax.inject.Inject;
39import javax.inject.Named;
40 
41import org.jclouds.date.DateService;
42import org.jclouds.date.internal.SimpleDateFormatDateService;
43import org.jclouds.http.options.BaseHttpRequestOptions;
44import org.jclouds.s3.domain.CannedAccessPolicy;
45 
46import com.google.common.base.Preconditions;
47import com.google.common.collect.ImmutableMultimap;
48import com.google.common.collect.Multimap;
49 
50/**
51 * Contains options supported in the REST API for the COPY object operation.
52 * <p/>
53 * <h2>Usage</h2> The recommended way to instantiate a CopyObjectOptions object is to statically
54 * import CopyObjectOptions.Builder.* and invoke a static creation method followed by an instance
55 * mutator (if needed):
56 * <p/>
57 * <code>
58 * import static org.jclouds.s3.commands.options.CopyObjectOptions.Builder.*
59 * <p/>
60 * S3Client connection = // get connection
61 * <p/>
62 * Multimap<String,String> metadata = LinkedHashMultimap.create();
63 * metadata.put("x-amz-meta-adrian", "foo");
64 * <p/>
65 * // this will copy the object, provided it wasn't modified since yesterday.
66 * // it will not use metadata from the source, and instead use what we pass in.
67 * Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
68 * "destinationBucket", "destinationName",
69 * overrideMetadataWith(meta).
70 * ifSourceModifiedSince(new Date().minusDays(1))
71 * );
72 * <code>
73 * 
74 * @author Adrian Cole
75 * @see <a
76 *      href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?"
77 *      />
78 */
79public class CopyObjectOptions extends BaseHttpRequestOptions {
80   private final static DateService dateService = new SimpleDateFormatDateService();
81   public static final CopyObjectOptions NONE = new CopyObjectOptions();
82   private Map<String, String> metadata;
83   private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
84 
85   private String metadataPrefix;
86 
87   @Inject
88   public void setMetadataPrefix(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
89      this.metadataPrefix = metadataPrefix;
90   }
91 
92   private String headerTag;
93 
94   @Inject
95   public void setHeaderTag(@Named(PROPERTY_HEADER_TAG) String headerTag) {
96      this.headerTag = headerTag;
97   }
98 
99   /**
100    * Override the default ACL (private) with the specified one.
101    * 
102    * @see CannedAccessPolicy
103    */
104   public CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
105      this.acl = checkNotNull(acl, "acl");
106      if (!acl.equals(CannedAccessPolicy.PRIVATE))
107         this.replaceHeader(CANNED_ACL, acl.toString());
108      return this;
109   }
110 
111   /**
112    * @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
113    */
114   public CannedAccessPolicy getAcl() {
115      return acl;
116   }
117 
118   /**
119    * For use in the header x-amz-copy-source-if-unmodified-since
120    * <p/>
121    * Copies the object if it hasn't been modified since the specified time; otherwise returns a 412
122    * (precondition failed).
123    * <p/>
124    * This header can be used with x-amz-copy-source-if-match, but cannot be used with other
125    * conditional copy headers.
126    * 
127    * @return valid HTTP date
128    * @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
129    * @see CopyObjectOptions#ifSourceModifiedSince(Date)
130    */
131   public String getIfModifiedSince() {
132      return getFirstHeaderOrNull(COPY_SOURCE_IF_MODIFIED_SINCE);
133   }
134 
135   /**
136    * For use in the header x-amz-copy-source-if-modified-since
137    * <p/>
138    * Copies the object if it has been modified since the specified time; otherwise returns a 412
139    * (failed condition).
140    * <p/>
141    * This header can be used with x-amz-copy-source-if-none-match, but cannot be used with other
142    * conditional copy headers.
143    * 
144    * @return valid HTTP date
145    * @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
146    * @see CopyObjectOptions#ifSourceUnmodifiedSince(Date)
147    */
148   public String getIfUnmodifiedSince() {
149      return getFirstHeaderOrNull(COPY_SOURCE_IF_UNMODIFIED_SINCE);
150   }
151 
152   /**
153    * For use in the request header: x-amz-copy-source-if-match
154    * <p/>
155    * Copies the object if its payload tag (ETag) matches the specified tag; otherwise return a 412
156    * (precondition failed).
157    * <p/>
158    * This header can be used with x-amz-copy-source-if-unmodified-since, but cannot be used with
159    * other conditional copy headers.
160    * 
161    * @see CopyObjectOptions#ifSourceETagMatches(String)
162    */
163   public String getIfMatch() {
164      return getFirstHeaderOrNull(COPY_SOURCE_IF_MATCH);
165   }
166 
167   /**
168    * For use in the request header: x-amz-copy-source-if-none-match
169    * <p/>
170    * Copies the object if its payload tag (ETag) is different than the specified Etag; otherwise
171    * returns a 412 (failed condition).
172    * <p/>
173    * This header can be used with x-amz-copy-source-if-modified-since, but cannot be used with
174    * other conditional copy headers.
175    * 
176    * @see CopyObjectOptions#ifSourceETagDoesntMatch(String)
177    */
178   public String getIfNoneMatch() {
179      return getFirstHeaderOrNull(COPY_SOURCE_IF_NO_MATCH);
180   }
181 
182   /**
183    * When not null, contains the header [x-amz-copy-source-if-unmodified-since] -> [REPLACE] and
184    * metadata headers passed in from the users.
185    * 
186    * @see #overrideMetadataWith(Multimap)
187    */
188   public Map<String, String> getMetadata() {
189      return metadata;
190   }
191 
192   /**
193    * Only return the object if it has changed since this time.
194    * <p/>
195    * Not compatible with {@link #ifSourceETagMatches(String)} or
196    * {@link #ifSourceUnmodifiedSince(Date)}
197    */
198   public CopyObjectOptions ifSourceModifiedSince(Date ifModifiedSince) {
199      checkState(getIfMatch() == null, "ifETagMatches() is not compatible with ifModifiedSince()");
200      checkState(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifModifiedSince()");
201      replaceHeader(COPY_SOURCE_IF_MODIFIED_SINCE, dateService.rfc822DateFormat(checkNotNull(ifModifiedSince,
202               "ifModifiedSince")));
203      return this;
204   }
205 
206   /**
207    * Only return the object if it hasn't changed since this time.
208    * <p/>
209    * Not compatible with {@link #ifSourceETagDoesntMatch(String)} or
210    * {@link #ifSourceModifiedSince(Date)}
211    */
212   public CopyObjectOptions ifSourceUnmodifiedSince(Date ifUnmodifiedSince) {
213      checkState(getIfNoneMatch() == null, "ifETagDoesntMatch() is not compatible with ifUnmodifiedSince()");
214      checkState(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifUnmodifiedSince()");
215      replaceHeader(COPY_SOURCE_IF_UNMODIFIED_SINCE, dateService.rfc822DateFormat(checkNotNull(ifUnmodifiedSince,
216               "ifUnmodifiedSince")));
217      return this;
218   }
219 
220   /**
221    * The object's eTag hash should match the parameter <code>eTag</code>.
222    * <p/>
223    * <p/>
224    * Not compatible with {@link #ifSourceETagDoesntMatch(String)} or
225    * {@link #ifSourceModifiedSince(Date)}
226    * 
227    * @param eTag
228    *           hash representing the payload
229    */
230   public CopyObjectOptions ifSourceETagMatches(String eTag) throws UnsupportedEncodingException {
231      checkState(getIfNoneMatch() == null, "ifETagDoesntMatch() is not compatible with ifETagMatches()");
232      checkState(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifETagMatches()");
233      replaceHeader(COPY_SOURCE_IF_MATCH, String.format("\"%1$s\"", checkNotNull(eTag, "eTag")));
234      return this;
235   }
236 
237   /**
238    * The object should not have a eTag hash corresponding with the parameter <code>eTag</code>.
239    * <p/>
240    * Not compatible with {@link #ifSourceETagMatches(String)} or
241    * {@link #ifSourceUnmodifiedSince(Date)}
242    * 
243    * @param eTag
244    *           hash representing the payload
245    * @throws UnsupportedEncodingException
246    *            if there was a problem converting this into an S3 eTag string
247    */
248   public CopyObjectOptions ifSourceETagDoesntMatch(String eTag) throws UnsupportedEncodingException {
249      checkState(getIfMatch() == null, "ifETagMatches() is not compatible with ifETagDoesntMatch()");
250      Preconditions.checkState(getIfUnmodifiedSince() == null,
251               "ifUnmodifiedSince() is not compatible with ifETagDoesntMatch()");
252      replaceHeader(COPY_SOURCE_IF_NO_MATCH, String.format("\"%s\"", checkNotNull(eTag, "ifETagDoesntMatch")));
253      return this;
254   }
255 
256   @Override
257   public Multimap<String, String> buildRequestHeaders() {
258      checkState(headerTag != null, "headerTag should have been injected!");
259      checkState(metadataPrefix != null, "metadataPrefix should have been injected!");
260      ImmutableMultimap.Builder<String, String> returnVal = ImmutableMultimap.<String, String> builder();
261      for (Entry<String, String> entry : headers.entries()) {
262         returnVal.put(entry.getKey().replace(DEFAULT_AMAZON_HEADERTAG, headerTag), entry.getValue());
263      }
264      if (metadata != null) {
265         returnVal.put(METADATA_DIRECTIVE.replace(DEFAULT_AMAZON_HEADERTAG, headerTag), "REPLACE");
266         for (String key : metadata.keySet()) {
267            returnVal.put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key, metadata.get(key));
268         }
269      }
270      return returnVal.build();
271   }
272 
273   /**
274    * Use the provided metadata instead of what is on the source object.
275    */
276   public CopyObjectOptions overrideMetadataWith(Map<String, String> metadata) {
277      checkNotNull(metadata, "metadata");
278      this.metadata = metadata;
279      return this;
280   }
281 
282   public static class Builder {
283      /**
284       * @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
285       */
286      public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
287         CopyObjectOptions options = new CopyObjectOptions();
288         return options.overrideAcl(acl);
289      }
290 
291      /**
292       * @see CopyObjectOptions#getIfModifiedSince()
293       */
294      public static CopyObjectOptions ifSourceModifiedSince(Date ifModifiedSince) {
295         CopyObjectOptions options = new CopyObjectOptions();
296         return options.ifSourceModifiedSince(ifModifiedSince);
297      }
298 
299      /**
300       * @see CopyObjectOptions#ifSourceUnmodifiedSince(Date)
301       */
302      public static CopyObjectOptions ifSourceUnmodifiedSince(Date ifUnmodifiedSince) {
303         CopyObjectOptions options = new CopyObjectOptions();
304         return options.ifSourceUnmodifiedSince(ifUnmodifiedSince);
305      }
306 
307      /**
308       * @see CopyObjectOptions#ifSourceETagMatches(String)
309       */
310      public static CopyObjectOptions ifSourceETagMatches(String eTag) throws UnsupportedEncodingException {
311         CopyObjectOptions options = new CopyObjectOptions();
312         return options.ifSourceETagMatches(eTag);
313      }
314 
315      /**
316       * @see CopyObjectOptions#ifSourceETagDoesntMatch(String)
317       */
318      public static CopyObjectOptions ifSourceETagDoesntMatch(String eTag) throws UnsupportedEncodingException {
319         CopyObjectOptions options = new CopyObjectOptions();
320         return options.ifSourceETagDoesntMatch(eTag);
321      }
322 
323      /**
324       * @see #overrideMetadataWith(Multimap)
325       */
326      public static CopyObjectOptions overrideMetadataWith(Map<String, String> metadata) {
327         CopyObjectOptions options = new CopyObjectOptions();
328         return options.overrideMetadataWith(metadata);
329      }
330   }
331}

[all classes][org.jclouds.s3.options]
EMMA 2.0.5312 (C) Vladimir Roubtsov