Skip to content

Commit 3ba2362

Browse files
author
arnett, stu
committed
v2.2.1
1 parent 8bbcb0f commit 3ba2362

13 files changed

+126
-95
lines changed

src/main/java/com/emc/object/s3/bean/QueryMetadata.java

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,16 @@
2727
package com.emc.object.s3.bean;
2828

2929
import javax.xml.bind.annotation.XmlElement;
30-
import javax.xml.bind.annotation.XmlElementWrapper;
31-
import javax.xml.bind.annotation.XmlTransient;
3230
import javax.xml.bind.annotation.XmlType;
33-
import java.util.ArrayList;
3431
import java.util.HashMap;
35-
import java.util.List;
3632
import java.util.Map;
3733

38-
@XmlType(propOrder = {"type", "queryMetadataEntries"})
34+
@XmlType(namespace = "")
3935
public class QueryMetadata {
4036
private QueryMetadataType type;
4137
private Map<String, String> mdMap = new HashMap<String, String>();
4238

43-
@XmlElement(name = "type", namespace = "")
39+
@XmlElement(name = "type")
4440
public QueryMetadataType getType() {
4541
return type;
4642
}
@@ -49,67 +45,12 @@ public void setType(QueryMetadataType type) {
4945
this.type = type;
5046
}
5147

52-
@XmlTransient
48+
@XmlElement(name = "mdMap")
5349
public Map<String, String> getMdMap() {
5450
return mdMap;
5551
}
5652

5753
public void setMdMap(Map<String, String> mdMap) {
5854
this.mdMap = mdMap;
5955
}
60-
61-
/**
62-
* @deprecated Use {@link #getMdMap()} instead.
63-
*/
64-
@XmlElementWrapper(name = "mdMap", namespace = "")
65-
@XmlElement(name = "entry", namespace = "")
66-
public List<QueryMetadataEntry> getQueryMetadataEntries() {
67-
if (mdMap == null) return null;
68-
List<QueryMetadataEntry> queryMetadataEntries = new ArrayList<QueryMetadataEntry>();
69-
for (String key : mdMap.keySet()) {
70-
queryMetadataEntries.add(new QueryMetadataEntry(key, mdMap.get(key)));
71-
}
72-
return queryMetadataEntries;
73-
}
74-
75-
/**
76-
* @deprecated Use {@link #setMdMap(Map)} instead.
77-
*/
78-
public void setQueryMetadataEntries(List<QueryMetadataEntry> queryMetadataEntries) {
79-
mdMap = new HashMap<String, String>();
80-
for (QueryMetadataEntry entry : queryMetadataEntries) {
81-
mdMap.put(entry.getKey(), entry.getValue());
82-
}
83-
}
84-
85-
public static class QueryMetadataEntry {
86-
private String key;
87-
private String value;
88-
89-
public QueryMetadataEntry() {
90-
}
91-
92-
public QueryMetadataEntry(String key, String value) {
93-
this.key = key;
94-
this.value = value;
95-
}
96-
97-
@XmlElement(name = "key", namespace = "")
98-
public String getKey() {
99-
return key;
100-
}
101-
102-
public void setKey(String key) {
103-
this.key = key;
104-
}
105-
106-
@XmlElement(name = "value", namespace = "")
107-
public String getValue() {
108-
return value;
109-
}
110-
111-
public void setValue(String value) {
112-
this.value = value;
113-
}
114-
}
11556
}

src/main/java/com/emc/object/s3/bean/QueryObject.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@
3131
import java.util.ArrayList;
3232
import java.util.List;
3333

34-
@XmlType(propOrder = {"objectName", "objectId", "versionId", "queryMds"})
34+
@XmlType(propOrder = {"objectName", "objectId", "versionId", "queryMds"}, namespace = "")
3535
public class QueryObject {
3636
private String objectName;
3737
private String objectId;
3838
private String versionId;
3939
private List<QueryMetadata> queryMds = new ArrayList<QueryMetadata>();
4040

41-
@XmlElement(name = "objectName", namespace = "")
41+
@XmlElement(name = "objectName")
4242
public String getObjectName() {
4343
return objectName;
4444
}
@@ -47,14 +47,14 @@ public void setObjectName(String objectName) {
4747
this.objectName = objectName;
4848
}
4949

50-
@XmlElement(name = "objectId", namespace = "")
50+
@XmlElement(name = "objectId")
5151
public String getObjectId() {
5252
return objectId;
5353
}
5454

5555
public void setObjectId(String objectId) { this.objectId = objectId; }
5656

57-
@XmlElement(name = "versionId", namespace = "")
57+
@XmlElement(name = "versionId")
5858
public String getVersionId() {
5959
return versionId;
6060
}
@@ -63,7 +63,7 @@ public void setVersionId(String versionId) {
6363
this.versionId = versionId;
6464
}
6565

66-
@XmlElement(name = "queryMds", namespace = "")
66+
@XmlElement(name = "queryMds")
6767
public List<QueryMetadata> getQueryMds() {
6868
return queryMds;
6969
}

src/main/java/com/emc/object/s3/bean/QueryObjectsResult.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import java.util.List;
3232

3333
@XmlRootElement(name = "BucketQueryResult", namespace = "")
34-
@XmlType(propOrder = {"bucketName", "marker", "nextMarker", "maxKeys", "objects"})
34+
@XmlType(propOrder = {"bucketName", "marker", "nextMarker", "maxKeys", "objects"}, namespace = "")
3535
public class QueryObjectsResult {
3636
private String bucketName;
3737
private Integer maxKeys;
@@ -43,7 +43,7 @@ public class QueryObjectsResult {
4343
private String sorted;
4444
private boolean includeOlderVersions = false;
4545

46-
@XmlElement(name = "Name", namespace = "")
46+
@XmlElement(name = "Name")
4747
public String getBucketName() {
4848
return bucketName;
4949
}
@@ -52,7 +52,7 @@ public void setBucketName(String bucketName) {
5252
this.bucketName = bucketName;
5353
}
5454

55-
@XmlElement(name = "Marker", namespace = "")
55+
@XmlElement(name = "Marker")
5656
public String getMarker() {
5757
return marker;
5858
}
@@ -61,7 +61,7 @@ public void setMarker(String marker) {
6161
this.marker = marker;
6262
}
6363

64-
@XmlElement(name = "NextMarker", namespace = "")
64+
@XmlElement(name = "NextMarker")
6565
public String getNextMarker() {
6666
return nextMarker;
6767
}
@@ -70,7 +70,7 @@ public void setNextMarker(String nextMarker) {
7070
this.nextMarker = nextMarker;
7171
}
7272

73-
@XmlElement(name = "MaxKeys", namespace = "")
73+
@XmlElement(name = "MaxKeys")
7474
public Integer getMaxKeys() {
7575
return maxKeys;
7676
}
@@ -84,8 +84,8 @@ public boolean isTruncated() {
8484
return nextMarker != null && !nextMarker.isEmpty() && !"NO MORE PAGES".equals(nextMarker);
8585
}
8686

87-
@XmlElementWrapper(name = "ObjectMatches", namespace = "")
88-
@XmlElement(name = "object", namespace = "")
87+
@XmlElementWrapper(name = "ObjectMatches")
88+
@XmlElement(name = "object")
8989
public List<QueryObject> getObjects() {
9090
return objects;
9191
}

src/main/java/com/emc/object/s3/jersey/ErrorFilter.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import com.emc.object.s3.S3Constants;
3030
import com.emc.object.s3.S3Exception;
31+
import com.emc.object.util.RestUtil;
3132
import com.sun.jersey.api.client.ClientHandlerException;
3233
import com.sun.jersey.api.client.ClientRequest;
3334
import com.sun.jersey.api.client.ClientResponse;
@@ -41,6 +42,7 @@
4142
import javax.ws.rs.core.Response;
4243
import java.io.InputStreamReader;
4344
import java.io.Reader;
45+
import java.util.Date;
4446

4547
public class ErrorFilter extends ClientFilter {
4648
private static final Logger l4j = Logger.getLogger(ErrorFilter.class);
@@ -49,6 +51,20 @@ public ClientResponse handle(ClientRequest request) throws ClientHandlerExceptio
4951
ClientResponse response = getNext().handle(request);
5052

5153
if (response.getStatus() > 299) {
54+
55+
// check for clock skew (can save hours of troubleshooting)
56+
if (response.getStatus() == 403) {
57+
Date clientTime = RestUtil.headerParse(RestUtil.getFirstAsString(request.getHeaders(), S3Constants.AMZ_DATE));
58+
if (clientTime == null)
59+
clientTime = RestUtil.headerParse(RestUtil.getFirstAsString(request.getHeaders(), RestUtil.HEADER_DATE));
60+
Date serverTime = RestUtil.headerParse(RestUtil.getFirstAsString(response.getHeaders(), RestUtil.HEADER_DATE));
61+
if (clientTime != null && serverTime != null) {
62+
long skew = clientTime.getTime() - serverTime.getTime();
63+
if (Math.abs(skew) > 5 * 60 * 1000) { // +/- 5 minutes
64+
l4j.warn("clock skew detected! client is more than 5 minutes off from server (" + skew + "ms)");
65+
}
66+
}
67+
}
5268
if(response.hasEntity()) {
5369
throw parseErrorResponse(new InputStreamReader(response.getEntityInputStream()), response.getStatus());
5470
} else {

src/test/java/com/emc/object/s3/AbstractS3ClientTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ public abstract class AbstractS3ClientTest extends AbstractClientTest {
4848

4949
protected S3Client client;
5050

51+
protected abstract S3Client createS3Client() throws Exception;
52+
53+
protected final void initClient() throws Exception {
54+
this.client = createS3Client();
55+
}
56+
5157
@After
5258
public void dumpLBStats() {
5359
if (client != null) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2015-2016, EMC Corporation.
3+
* Redistribution and use in source and binary forms, with or without modification,
4+
* are permitted provided that the following conditions are met:
5+
*
6+
* + Redistributions of source code must retain the above copyright notice,
7+
* this list of conditions and the following disclaimer.
8+
* + Redistributions in binary form must reproduce the above copyright
9+
* notice, this list of conditions and the following disclaimer in the
10+
* documentation and/or other materials provided with the distribution.
11+
* + The name of EMC Corporation may not be used to endorse or promote
12+
* products derived from this software without specific prior written
13+
* permission.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
19+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25+
* POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
package com.emc.object.s3;
28+
29+
import com.emc.object.s3.jersey.S3JerseyClient;
30+
import com.emc.object.s3.request.ListBucketsRequest;
31+
import com.emc.object.util.RestUtil;
32+
import org.junit.Assert;
33+
import org.junit.Test;
34+
35+
import java.util.Date;
36+
import java.util.List;
37+
import java.util.Map;
38+
39+
public class ClockSkewTest extends AbstractS3ClientTest {
40+
@Override
41+
protected S3Client createS3Client() throws Exception {
42+
return new S3JerseyClient(createS3Config());
43+
}
44+
45+
@Test
46+
public void testClockSkew() throws Exception {
47+
try {
48+
ListBucketsRequest request = new ListBucketsRequest() {
49+
@Override
50+
public Map<String, List<Object>> getHeaders() {
51+
Map<String, List<Object>> headers = super.getHeaders();
52+
// set x-amz-date, subtracting 30 minutes from current time
53+
Date oldDate = new Date(System.currentTimeMillis() - (30 * 60 * 1000));
54+
RestUtil.putSingle(headers, S3Constants.AMZ_DATE, RestUtil.headerFormat(oldDate));
55+
return headers;
56+
}
57+
};
58+
client.listBuckets(request);
59+
} catch (S3Exception e) {
60+
Assert.assertEquals(403, e.getHttpCode());
61+
}
62+
}
63+
}

src/test/java/com/emc/object/s3/GeoPinningTest.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,11 @@
5959
import java.util.*;
6060

6161
public class GeoPinningTest extends AbstractS3ClientTest {
62-
private S3Config s3Config;
6362
private List<Vdc> vdcs;
6463

6564
@Override
66-
protected void initClient() throws Exception {
67-
s3Config = createS3Config();
65+
protected S3Config createS3Config() throws Exception {
66+
S3Config s3Config = super.createS3Config();
6867
Assume.assumeFalse(s3Config.isUseVHost());
6968

7069
// just going to use the same VDC thrice for lack of a geo env.
@@ -81,10 +80,16 @@ protected void initClient() throws Exception {
8180
if (proxyUri != null) s3Config.setProperty(ObjectConfig.PROPERTY_PROXY_URI, proxyUri);
8281

8382
s3Config.setGeoPinningEnabled(true);
83+
return s3Config;
84+
}
8485

85-
client = new S3JerseyClient(s3Config);
86+
@Override
87+
protected S3Client createS3Client() throws Exception {
88+
S3Client client = new S3JerseyClient(createS3Config());
8689

8790
Thread.sleep(500); // wait for polling daemon to finish initial poll
91+
92+
return client;
8893
}
8994

9095
@Test
@@ -150,7 +155,7 @@ public void testVdcDistribution() {
150155

151156
@Test
152157
public void testReadRetryFailoverInFilter() throws Exception {
153-
S3Config s3ConfigF = new S3Config(s3Config);
158+
S3Config s3ConfigF = new S3Config(createS3Config());
154159
s3ConfigF.setGeoReadRetryFailover(true);
155160
GeoPinningFilter filter = new GeoPinningFilter(s3ConfigF);
156161

src/test/java/com/emc/object/s3/RetryFilterTest.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,21 @@
3636
import java.io.InputStream;
3737

3838
public class RetryFilterTest extends AbstractS3ClientTest {
39-
protected S3Config s3Config;
40-
4139
@Override
4240
protected String getTestBucketPrefix() {
4341
return "s3-retry-test";
4442
}
4543

4644
@Override
47-
protected void initClient() throws Exception {
48-
client = new S3JerseyClient(createS3Config());
49-
s3Config = ((S3JerseyClient) client).getS3Config();
45+
protected S3Client createS3Client() throws Exception {
46+
return new S3JerseyClient(createS3Config());
5047
}
5148

5249
@Test
5350
public void testRetryFilter() throws Exception {
5451
int retryLimit = 3;
5552
final String flagMessage = "XXXXX";
53+
S3Config s3Config = ((S3JerseyClient) client).getS3Config();
5654

5755
S3ObjectMetadata metadata = new S3ObjectMetadata().withContentLength(1).withContentType("text/plain");
5856
PutObjectRequest request = new PutObjectRequest(getTestBucket(), "foo",

src/test/java/com/emc/object/s3/S3EncryptionClientBasicTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ protected String getTestBucketPrefix() {
6969
}
7070

7171
@Override
72-
public void initClient() throws Exception {
72+
public S3Client createS3Client() throws Exception {
7373
rclient = new S3JerseyClient(createS3Config());
74-
client = eclient = new S3EncryptionClient(createS3Config(), createEncryptionConfig());
74+
eclient = new S3EncryptionClient(createS3Config(), createEncryptionConfig());
75+
return eclient;
7576
}
7677

7778
protected EncryptionConfig createEncryptionConfig() throws Exception {

0 commit comments

Comments
 (0)