Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@

package com.spectralogic.ds3client.helpers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.spectralogic.ds3client.Ds3Client;
import com.spectralogic.ds3client.commands.decorators.PutFolderResponse;
import com.spectralogic.ds3client.helpers.events.SameThreadEventRunner;
import com.spectralogic.ds3client.integration.Util;
import com.spectralogic.ds3client.integration.test.helpers.TempStorageIds;
Expand All @@ -31,6 +29,8 @@
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
Expand All @@ -39,17 +39,15 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import static com.spectralogic.ds3client.integration.Util.deleteAllContents;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;

public class FileSystemHelper_Test {
private static final Logger LOG = LoggerFactory.getLogger(FileSystemHelper_Test.class);
Expand Down Expand Up @@ -313,4 +311,28 @@ public long getAvailableFileSpace(final Path path) throws IOException {
throw new IOException("IOExceptionAtor");
}
}

@Test
public void createFolderWithSlash() throws IOException {
final String folderName = "FolderNameWithSlash/";

try {
final PutFolderResponse response = HELPERS.createFolder(BUCKET_NAME, folderName);
assertNotNull(response);
} finally {
deleteAllContents(client, BUCKET_NAME);
}
}

@Test
public void createFolderWithNoSlash() throws IOException {
final String folderName = "FolderNameNoSlash";

try {
final PutFolderResponse response = HELPERS.createFolder(BUCKET_NAME, folderName);
assertNotNull(response);
} finally {
deleteAllContents(client, BUCKET_NAME);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@

package com.spectralogic.ds3client.integration;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.spectralogic.ds3client.Ds3Client;
import com.spectralogic.ds3client.commands.*;
import com.spectralogic.ds3client.commands.decorators.PutFolderRequest;
import com.spectralogic.ds3client.commands.decorators.PutFolderResponse;
import com.spectralogic.ds3client.commands.interfaces.BulkResponse;
import com.spectralogic.ds3client.commands.spectrads3.*;
import com.spectralogic.ds3client.helpers.*;
Expand Down Expand Up @@ -1656,4 +1659,21 @@ public void testGetObjectsWithFullDetails() throws IOException, URISyntaxExcepti
deleteAllContents(client, bucketName);
}
}

@Test
public void createFolderWithSlash() throws IOException {
final String folderName = "FolderNameWithSlash/";
final String bucketName = "FolderNameWithSlashTestBucket";

try {
HELPERS.ensureBucketExists(bucketName, envDataPolicyId);
final Ds3Object ds3Object = new Ds3Object(folderName, 0);
final PutBulkJobSpectraS3Response jobResponse = client.putBulkJobSpectraS3(new PutBulkJobSpectraS3Request(bucketName, ImmutableList.of(ds3Object)));

final PutFolderResponse response = client.putFolder(new PutFolderRequest(bucketName, folderName, jobResponse.getMasterObjectList().getJobId()));
assertNotNull(response);
} finally {
deleteAllContents(client, bucketName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import com.spectralogic.ds3client.annotations.Resource;
import com.spectralogic.ds3client.annotations.ResponsePayloadModel;
import com.spectralogic.ds3client.commands.*;
import com.spectralogic.ds3client.commands.decorators.PutFolderRequest;
import com.spectralogic.ds3client.commands.decorators.PutFolderResponse;
import com.spectralogic.ds3client.commands.spectrads3.*;
import com.spectralogic.ds3client.commands.spectrads3.notifications.*;
import com.spectralogic.ds3client.models.JobNode;
Expand All @@ -35,6 +37,8 @@ public interface Ds3Client extends Closeable {

ConnectionDetails getConnectionDetails();

PutFolderResponse putFolder(final PutFolderRequest request)
throws IOException;


AbortMultiPartUploadResponse abortMultiPartUpload(final AbortMultiPartUploadRequest request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import java.io.IOException;
import com.spectralogic.ds3client.commands.*;
import com.spectralogic.ds3client.commands.decorators.PutFolderRequest;
import com.spectralogic.ds3client.commands.decorators.PutFolderResponse;
import com.spectralogic.ds3client.commands.parsers.*;
import com.spectralogic.ds3client.commands.spectrads3.*;
import com.spectralogic.ds3client.commands.spectrads3.notifications.*;
Expand Down Expand Up @@ -45,6 +47,12 @@ public ConnectionDetails getConnectionDetails() {
return this.netClient.getConnectionDetails();
}

@Override
public PutFolderResponse putFolder(final PutFolderRequest request) throws IOException {
final PutObjectResponse response = putObject(request.getPutObjectRequest());
return new PutFolderResponse(response);
}

@Override
public AbortMultiPartUploadResponse abortMultiPartUpload(final AbortMultiPartUploadRequest request) throws IOException {
return new AbortMultiPartUploadResponseParser().response(this.netClient.getResponse(request));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* ******************************************************************************
* Copyright 2014-2017 Spectra Logic Corporation. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
* this file except in compliance with the License. A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file.
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* ****************************************************************************
*/

package com.spectralogic.ds3client.commands.decorators;

import com.spectralogic.ds3client.commands.PutObjectRequest;
import com.spectralogic.ds3client.exceptions.FolderNameMissingTrailingForwardSlash;

import java.util.UUID;

/**
* Decorates the {@link com.spectralogic.ds3client.commands.PutObjectRequest} and is used to
* ensure the correct creation of a folder using the Put Object command.
*
* A folder is created by putting an object with no content, of zero size, and with the
* content-length=0. Also, the name of the folder must end with a forward slash '/'.
*/
public class PutFolderRequest {

private final PutObjectRequest putObjectRequest;

public PutFolderRequest(final String bucketName, final String folderName, final UUID job) {
validateNameEndsWithSlash(folderName);
putObjectRequest = new PutObjectRequest(bucketName, folderName, job, 0, 0, null);
putObjectRequest.getHeaders().put("Content-Length", "0");
}

private static void validateNameEndsWithSlash(final String folderName) {
if (!folderName.endsWith("/")) {
throw new FolderNameMissingTrailingForwardSlash(folderName);
}
}

public PutObjectRequest getPutObjectRequest() {
return putObjectRequest;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* ******************************************************************************
* Copyright 2014-2017 Spectra Logic Corporation. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
* this file except in compliance with the License. A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file.
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* ****************************************************************************
*/

package com.spectralogic.ds3client.commands.decorators;

import com.spectralogic.ds3client.commands.PutObjectResponse;

/**
* Decorates the {@link com.spectralogic.ds3client.commands.PutObjectResponse} and is used
* by command {@link com.spectralogic.ds3client.Ds3Client#putFolder(PutFolderRequest)}
*/
public class PutFolderResponse extends PutObjectResponse {

public PutFolderResponse(final PutObjectResponse response) {
super(response.getChecksum(), response.getChecksumType());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* ******************************************************************************
* Copyright 2014-2017 Spectra Logic Corporation. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
* this file except in compliance with the License. A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file.
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* ****************************************************************************
*/

package com.spectralogic.ds3client.exceptions;

/**
* Denotes an invalid folder name. Folder names must end with a forward slash '/'.
*/
public class FolderNameMissingTrailingForwardSlash extends IllegalArgumentException {

public FolderNameMissingTrailingForwardSlash(final String folderName) {
super("Invalid folder name '" + folderName + "': folder names must end with a forward slash '/'.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.spectralogic.ds3client.Ds3Client;
import com.spectralogic.ds3client.commands.decorators.PutFolderResponse;
import com.spectralogic.ds3client.helpers.options.ReadJobOptions;
import com.spectralogic.ds3client.helpers.options.WriteJobOptions;
import com.spectralogic.ds3client.helpers.strategy.transferstrategy.TransferStrategy;
Expand Down Expand Up @@ -580,4 +581,9 @@ public static String stripLeadingPath(final String objectName, final String pref
public abstract ObjectStorageSpaceVerificationResult objectsFromBucketWillFitInDirectory(final String bucketName,
final Collection<String> objectNames,
final Path destinationDirectory);

/**
* Creates a folder in the specified bucket
*/
public abstract PutFolderResponse createFolder(final String bucketName, final String folderName) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.spectralogic.ds3client.commands.HeadBucketRequest;
import com.spectralogic.ds3client.commands.HeadBucketResponse;
import com.spectralogic.ds3client.commands.PutBucketRequest;
import com.spectralogic.ds3client.commands.decorators.PutFolderRequest;
import com.spectralogic.ds3client.commands.decorators.PutFolderResponse;
import com.spectralogic.ds3client.commands.spectrads3.*;
import com.spectralogic.ds3client.helpers.events.EventRunner;
import com.spectralogic.ds3client.helpers.events.SameThreadEventRunner;
Expand Down Expand Up @@ -593,4 +595,28 @@ public ObjectStorageSpaceVerificationResult objectsFromBucketWillFitInDirectory(
return fileSystemHelper.objectsFromBucketWillFitInDirectory(this,
bucketName, objectNames, destinationDirectory);
}

/**
* Creates a folder in the specified bucket.
*/
@Override
public PutFolderResponse createFolder(final String bucketName, final String folderName) throws IOException {
final String normalizedFolderName = ensureNameEndsWithSlash(folderName);
final Ds3Object ds3Object = new Ds3Object(normalizedFolderName, 0);
final PutBulkJobSpectraS3Response jobResponse = client
.putBulkJobSpectraS3(new PutBulkJobSpectraS3Request(bucketName, ImmutableList.of(ds3Object)));

return client.putFolder(new PutFolderRequest(bucketName, normalizedFolderName, jobResponse.getMasterObjectList().getJobId()));
}

/**
* Ensures that a folder names ends with a trailing forward slash. This prevents the
* accidental creation of zero-length files when attempting to create a folder.
*/
private static String ensureNameEndsWithSlash(final String folderName) {
if (folderName.endsWith("/")) {
return folderName;
}
return folderName + "/";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap;
import com.spectralogic.ds3client.commands.*;
import com.spectralogic.ds3client.commands.decorators.PutFolderRequest;
import com.spectralogic.ds3client.commands.spectrads3.*;
import com.spectralogic.ds3client.exceptions.ContentLengthNotMatchException;
import com.spectralogic.ds3client.exceptions.FolderNameMissingTrailingForwardSlash;
import com.spectralogic.ds3client.models.*;
import com.spectralogic.ds3client.models.Objects;
import com.spectralogic.ds3client.models.bulk.Ds3Object;
Expand Down Expand Up @@ -1136,4 +1138,9 @@ public void getObjectVerifyFullPayload() throws IOException {
jobIdString,
0));
}

@Test (expected = FolderNameMissingTrailingForwardSlash.class)
public void createFolderWithNoSlash() throws IOException {
new PutFolderRequest("BucketName", "FolderNameNoSlash", UUID.randomUUID());
}
}