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

COVERAGE SUMMARY FOR SOURCE FILE [ParseObjectMetadataFromHeaders.java]

nameclass, %method, %block, %line, %
ParseObjectMetadataFromHeaders.java100% (1/1)83%  (5/6)89%  (102/114)90%  (26/29)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ParseObjectMetadataFromHeaders100% (1/1)83%  (5/6)89%  (102/114)90%  (26/29)
setContext (HttpRequest): ParseObjectMetadataFromHeaders 0%   (0/1)0%   (0/12)0%   (0/3)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
ParseObjectMetadataFromHeaders (ParseSystemAndUserMetadataFromHeaders, BlobTo... 100% (1/1)100% (12/12)100% (5/5)
addETagTo (HttpResponse, MutableObjectMetadata): void 100% (1/1)100% (21/21)100% (5/5)
apply (HttpResponse): MutableObjectMetadata 100% (1/1)100% (58/58)100% (13/13)
setKey (String): ParseObjectMetadataFromHeaders 100% (1/1)100% (7/7)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.functions;
20 
21import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
22 
23import java.util.regex.Matcher;
24import java.util.regex.Pattern;
25 
26import javax.inject.Inject;
27import javax.inject.Named;
28import javax.ws.rs.core.HttpHeaders;
29 
30import org.jclouds.blobstore.domain.BlobMetadata;
31import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
32import org.jclouds.crypto.CryptoStreams;
33import org.jclouds.http.HttpRequest;
34import org.jclouds.http.HttpResponse;
35import org.jclouds.rest.InvocationContext;
36import org.jclouds.s3.blobstore.functions.BlobToObjectMetadata;
37import org.jclouds.s3.domain.MutableObjectMetadata;
38 
39import com.google.common.annotations.VisibleForTesting;
40import com.google.common.base.Function;
41 
42/**
43 * This parses @{link {@link org.jclouds.s3.domain.internal.MutableObjectMetadata} from HTTP
44 * headers.
45 * 
46 * @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" />
47 * @author Adrian Cole
48 */
49public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, MutableObjectMetadata>,
50         InvocationContext<ParseObjectMetadataFromHeaders> {
51   private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
52   private final BlobToObjectMetadata blobToObjectMetadata;
53   private final String userMdPrefix;
54 
55   @Inject
56   public ParseObjectMetadataFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
57            BlobToObjectMetadata blobToObjectMetadata, @Named(PROPERTY_USER_METADATA_PREFIX) String userMdPrefix) {
58      this.blobMetadataParser = blobMetadataParser;
59      this.blobToObjectMetadata = blobToObjectMetadata;
60      this.userMdPrefix = userMdPrefix;
61   }
62 
63   // eTag pattern can be "a34d7e626b350d2e326196085dfa52f4-1", which is opaque and shouldn't be
64   // used as content-md5, so filter etags that contain hyphens
65   static final Pattern MD5_FROM_ETAG = Pattern.compile("^\"?([0-9a-f]+)\"?$");
66 
67   /**
68    * parses the http response headers to create a new
69    * {@link org.jclouds.s3.domain.internal.MutableObjectMetadata} object.
70    */
71   public MutableObjectMetadata apply(HttpResponse from) {
72      BlobMetadata base = blobMetadataParser.apply(from);
73      MutableObjectMetadata to = blobToObjectMetadata.apply(base);
74 
75      addETagTo(from, to);
76      if (to.getContentMetadata().getContentMD5() == null && to.getETag() != null) {
77         Matcher md5Matcher = MD5_FROM_ETAG.matcher(to.getETag());
78         if (md5Matcher.find()) {
79            byte[] md5 = CryptoStreams.hex(md5Matcher.group(1));
80            // it is possible others will look at the http payload directly
81            if (from.getPayload() != null)
82               from.getPayload().getContentMetadata().setContentMD5(md5);
83            to.getContentMetadata().setContentMD5(md5);
84         }
85      }
86      // amz has an etag, but matches syntax for usermetadata
87      to.getUserMetadata().remove("object-etag");
88      to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL));
89      return to;
90   }
91 
92   /**
93    * ETag == Content-MD5
94    */
95   @VisibleForTesting
96   protected void addETagTo(HttpResponse from, MutableObjectMetadata metadata) {
97      if (metadata.getETag() == null) {
98         String eTagHeader = from.getFirstHeaderOrNull(userMdPrefix + "object-eTag");
99         if (eTagHeader != null) {
100            metadata.setETag(eTagHeader);
101         }
102      }
103   }
104 
105   @Override
106   public ParseObjectMetadataFromHeaders setContext(HttpRequest request) {
107      blobMetadataParser.setContext(request);
108      blobToObjectMetadata.setContext(request);
109      return this;
110   }
111 
112   public ParseObjectMetadataFromHeaders setKey(String key) {
113      blobMetadataParser.setName(key);
114      return this;
115   }
116}

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