Commit 0bafa9e3 authored by Hema Vishnu Pola [Microsoft]'s avatar Hema Vishnu Pola [Microsoft]
Browse files

Merge branch 'users/amaverma/useBlobServiceClient' into 'master'

using BlobServiceCientFactory instead of BlobContainerClientFactory

See merge request !22
parents 8e2f6293 2cf76ba8
Pipeline #7188 passed with stages
in 2 minutes and 13 seconds
......@@ -21,7 +21,7 @@
<groupId>org.opengroup.osdu</groupId>
<artifactId>core-lib-azure</artifactId>
<packaging>jar</packaging>
<version>0.0.21</version>
<version>0.0.22</version>
<name>core-lib-azure</name>
<properties>
......
......@@ -15,6 +15,7 @@
package org.opengroup.osdu.azure.blobstorage;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.models.BlobErrorCode;
import com.azure.storage.blob.models.BlobStorageException;
import com.azure.storage.blob.specialized.BlockBlobClient;
......@@ -55,6 +56,23 @@ import java.util.Collections;;
* {
* Boolean success = blobStorage.deleteFromBlob("dataPartitionId", "filePath");
* }
*
* String readFromStorageContainerExamole()
* {
* String content = blobStorage.readFromStorageContainer("dataPartitionId", "filePath", "containerName");
* if (content != null)
* return content;
* }
*
* void writeToStorageContainerExample()
* {
* blobStorage.writeToStorageContainer("dataPartitionId", "filePath", "content", "containerName");
* }
*
* void deleteFromStorageContainerExample()
* {
* Boolean success = blobStorage.deleteFromStorageContainer("dataPartitionId", "filePath", "containerName");
* }
* }
* </pre>
*/
......@@ -66,6 +84,9 @@ public class BlobStore {
@Autowired
private IBlobContainerClientFactory blobContainerClientFactory;
@Autowired
private IBlobServiceClientFactory blobServiceClientFactory;
@Autowired
private ILogger logger;
......@@ -136,8 +157,8 @@ public class BlobStore {
* @param dataPartitionId Data partition id
*/
public void writeToBlob(final String dataPartitionId,
final String filePath,
final String content) {
final String filePath,
final String content) {
byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
int bytesSize = bytes.length;
BlobContainerClient blobContainerClient = getBlobContainerClient(dataPartitionId);
......@@ -155,6 +176,102 @@ public class BlobStore {
}
}
/**
*
* @param filePath Path of file to be read.
* @param dataPartitionId Data partition id
* @param containerName Name of the storage container
* @return the content of file with provided file path.
*/
public String readFromStorageContainer(
final String dataPartitionId,
final String filePath,
final String containerName) {
BlobContainerClient blobContainerClient = getBlobContainerClient(dataPartitionId, containerName);
BlockBlobClient blockBlobClient = blobContainerClient.getBlobClient(filePath).getBlockBlobClient();
try (ByteArrayOutputStream downloadStream = new ByteArrayOutputStream()) {
blockBlobClient.download(downloadStream);
return downloadStream.toString(StandardCharsets.UTF_8.name());
} catch (BlobStorageException ex) {
if (ex.getErrorCode().equals(BlobErrorCode.BLOB_NOT_FOUND)) {
String errorMessage = "Specified blob was not found";
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(404, errorMessage, ex.getMessage(), ex);
} else {
String errorMessage = "Failed to read specified blob";
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(500, errorMessage, ex.getMessage(), ex);
}
} catch (UnsupportedEncodingException ex) {
String errorMessage = String.format("Encoding was not correct for item with name=%s", filePath);
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(400, errorMessage, ex.getMessage(), ex);
} catch (IOException ex) {
String errorMessage = String.format("Malformed document for item with name=%s", filePath);
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(500, errorMessage, ex.getMessage(), ex);
}
}
/**
*
* @param filePath Path of file to be deleted.
* @param dataPartitionId Data partition id
* @param containerName Name of the storage container
* @return boolean indicating whether the deletion of given file was successful or not.
*/
public boolean deleteFromStorageContainer(
final String dataPartitionId,
final String filePath,
final String containerName) {
BlobContainerClient blobContainerClient = getBlobContainerClient(dataPartitionId, containerName);
BlockBlobClient blockBlobClient = blobContainerClient.getBlobClient(filePath).getBlockBlobClient();
try {
blockBlobClient.delete();
return true;
} catch (BlobStorageException ex) {
if (ex.getErrorCode().equals(BlobErrorCode.BLOB_NOT_FOUND)) {
String errorMessage = "Specified blob was not found";
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(404, errorMessage, ex.getMessage(), ex);
} else {
String errorMessage = "Failed to delete blob";
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(500, errorMessage, ex.getMessage(), ex);
}
}
}
/**
*
* @param filePath Path of file to be written at.
* @param content Content to be written in the file.
* @param dataPartitionId Data partition id
* @param containerName Name of the storage container
*/
public void writeToStorageContainer(
final String dataPartitionId,
final String filePath,
final String content,
final String containerName) {
byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
int bytesSize = bytes.length;
BlobContainerClient blobContainerClient = getBlobContainerClient(dataPartitionId, containerName);
BlockBlobClient blockBlobClient = blobContainerClient.getBlobClient(filePath).getBlockBlobClient();
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(bytes)) {
blockBlobClient.upload(dataStream, bytesSize, true);
} catch (BlobStorageException ex) {
String errorMessage = "Failed to upload file content.";
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(500, errorMessage, ex.getMessage(), ex);
} catch (IOException ex) {
String errorMessage = String.format("Malformed document for item with name=%s", filePath);
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(500, errorMessage, ex.getMessage(), ex);
}
}
/**
*
* @param dataPartitionId Data partition id
......@@ -169,5 +286,22 @@ public class BlobStore {
throw new AppException(500, errorMessage, ex.getMessage(), ex);
}
}
}
/**
*
* @param dataPartitionId Data partition id.
* @param containerName Name of storage container.
* @return blob container client corresponding to the dataPartitionId.
*/
private BlobContainerClient getBlobContainerClient(final String dataPartitionId, final String containerName) {
try {
BlobServiceClient serviceClient = blobServiceClientFactory.getBlobServiceClient(dataPartitionId);
return serviceClient.getBlobContainerClient(containerName);
} catch (Exception ex) {
String errorMessage = "Error creating creating blob container client.";
logger.warning(LOG_PREFIX, errorMessage, Collections.<String, String>emptyMap());
throw new AppException(500, errorMessage, ex.getMessage(), ex);
}
}
}
......@@ -16,6 +16,7 @@ package org.opengroup.osdu.azure.blobstorage;
import com.azure.storage.blob.BlobClient;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.models.BlobErrorCode;
import com.azure.storage.blob.models.BlobStorageException;
import com.azure.storage.blob.models.BlockBlobItem;
......@@ -44,6 +45,7 @@ public class BlobStoreTest {
private static final String PARTITION_ID = "dataPartitionId";
private static final String FILE_PATH = "filePath";
private static final String CONTENT = "hello world";
private static final String STORAGE_CONTAINER_NAME = "containerName";
@InjectMocks
BlobStore blobStore;
......@@ -51,6 +53,12 @@ public class BlobStoreTest {
@Mock
IBlobContainerClientFactory blobContainerClientFactory;
@Mock
IBlobServiceClientFactory blobServiceClientFactory;
@Mock
BlobServiceClient blobServiceClient;
@Mock
BlobContainerClient blobContainerClient;
......@@ -69,9 +77,11 @@ public class BlobStoreTest {
@BeforeEach
void init() {
initMocks(this);
lenient().doReturn(blobContainerClient).when(blobContainerClientFactory).getClient(PARTITION_ID);
lenient().doReturn(blobClient).when(blobContainerClient).getBlobClient(FILE_PATH);
lenient().doReturn(blockBlobClient).when(blobClient).getBlockBlobClient();
lenient().when(blobClient.getBlockBlobClient()).thenReturn(blockBlobClient);
lenient().when(blobContainerClient.getBlobClient(FILE_PATH)).thenReturn(blobClient);
lenient().when(blobServiceClient.getBlobContainerClient(STORAGE_CONTAINER_NAME)).thenReturn(blobContainerClient);
lenient().when(blobServiceClientFactory.getBlobServiceClient(PARTITION_ID)).thenReturn(blobServiceClient);
lenient().when(blobContainerClientFactory.getClient(PARTITION_ID)).thenReturn(blobContainerClient);
lenient().doNothing().when(logger).warning(eq("azure-core-lib"), any(), anyMap());
}
......@@ -216,6 +226,160 @@ public class BlobStoreTest {
}
}
@Test
public void readFromStorageContainer_ErrorCreatingBlobContainerClient()
{
doThrow(AppException.class).when(blobServiceClientFactory).getBlobServiceClient(eq(PARTITION_ID));
try {
String content = blobStore.readFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(500, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void readFromStorageContainer_ErrorCreatingBlobContainerClient_FromServiceClient()
{
doThrow(AppException.class).when(blobServiceClient).getBlobContainerClient(eq(STORAGE_CONTAINER_NAME));
try {
String content = blobStore.readFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(500, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void readFromStorageContainer_Success()
{
String content = blobStore.readFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
ArgumentCaptor<ByteArrayOutputStream> outputStream = ArgumentCaptor.forClass(ByteArrayOutputStream.class);
// validate that the download method is being invoked appropriately.
verify(blockBlobClient).download(outputStream.capture());
}
@Test
public void readFromStorageContainer_BlobNotFound()
{
BlobStorageException exception = mockStorageException(BlobErrorCode.BLOB_NOT_FOUND);
doThrow(exception).when(blockBlobClient).download(any());
try {
String content = blobStore.readFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(404, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void readFromStorageContainer_InternalError()
{
BlobStorageException exception = mockStorageException(BlobErrorCode.INTERNAL_ERROR);
doThrow(exception).when(blockBlobClient).download(any());
try {
String content = blobStore.readFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(500, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void deleteFromStorageContainer_ErrorCreatingBlobContainerClient()
{
doThrow(AppException.class).when(blobServiceClientFactory).getBlobServiceClient(eq(PARTITION_ID));
try {
blobStore.deleteFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(500, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void deleteFromStorageContainer_BlobNotFound()
{
BlobStorageException exception = mockStorageException(BlobErrorCode.BLOB_NOT_FOUND);
doThrow(exception).when(blockBlobClient).delete();
try {
blobStore.deleteFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(404, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void deleteFromStorageContainer_InternalError()
{
BlobStorageException exception = mockStorageException(BlobErrorCode.INTERNAL_ERROR);
doThrow(exception).when(blockBlobClient).delete();
try {
blobStore.deleteFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(500, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void deleteFromStorageContainer_Success()
{
doNothing().when(blockBlobClient).delete();
try {
blobStore.deleteFromStorageContainer(PARTITION_ID, FILE_PATH, STORAGE_CONTAINER_NAME);
} catch (Exception ex) {
fail("should not get any exception.");
}
}
@Test
public void writeToStorageContainer_ErrorCreatingBlobContainerClient()
{
doThrow(AppException.class).when(blobServiceClientFactory).getBlobServiceClient(eq(PARTITION_ID));
try {
blobStore.writeToStorageContainer(PARTITION_ID, FILE_PATH, CONTENT, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(500, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void writeToStorageContainer_InternalError()
{
BlobStorageException exception = mockStorageException(BlobErrorCode.INTERNAL_ERROR);
doThrow(exception).when(blockBlobClient).upload(any(), anyLong(), eq(true));
try {
blobStore.writeToStorageContainer(PARTITION_ID, FILE_PATH, CONTENT, STORAGE_CONTAINER_NAME);
} catch (AppException ex) {
assertEquals(500, ex.getError().getCode());
} catch (Exception ex) {
fail("should not get different error code");
}
}
@Test
public void writeToStorageContainer_Success()
{
doReturn(blockBlobItem).when(blockBlobClient).upload(any(), anyLong(), eq(true));
try {
blobStore.writeToStorageContainer(PARTITION_ID, FILE_PATH, CONTENT, STORAGE_CONTAINER_NAME);
} catch (Exception ex) {
fail("should not get any exception.");
}
}
private BlobStorageException mockStorageException(BlobErrorCode errorCode) {
BlobStorageException mockException = mock(BlobStorageException.class);
lenient().when(mockException.getErrorCode()).thenReturn(errorCode);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment