Implementation for searching resources on Azure Storage (#717)

* Initial implementation for searching resource on Azure Storage

* Added tests

* Reworked slightly using Optionals

* Reworked slightly using Optionals

Co-authored-by: Manfred Riem <mriem@manorrock.com>
This commit is contained in:
Manfred Riem 2020-07-06 18:23:16 -06:00 коммит произвёл GitHub
Родитель f468778f2d
Коммит 121c343086
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 390 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,179 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.cloud.storage;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.models.BlobContainerItem;
import com.azure.storage.blob.models.BlobItem;
import com.azure.storage.file.share.ShareClient;
import com.azure.storage.file.share.ShareServiceClient;
import com.azure.storage.file.share.models.ShareFileItem;
import com.azure.storage.file.share.models.ShareItem;
import static com.microsoft.azure.spring.cloud.storage.AzureStorageUtils.isAzureStorageResource;
import static com.microsoft.azure.spring.cloud.storage.StorageType.BLOB;
import static com.microsoft.azure.spring.cloud.storage.StorageType.FILE;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Optional;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.AntPathMatcher;
/**
* An Azure Storage specific ResourcePatternResolver.
*/
public class AzureStorageResourcePatternResolver implements ResourcePatternResolver {
/**
* Stores the Ant path matcher.
*/
private final AntPathMatcher matcher = new AntPathMatcher();
/**
* Stores the BlobServiceClient.
*/
private Optional<BlobServiceClient> blobServiceClient;
/**
* Stores the ShareServiceClient shareServiceClient
*/
private Optional<ShareServiceClient> shareServiceClient;
/**
* Constructor.
*
* @param blobServiceClient the BlobServiceClient.
*/
public AzureStorageResourcePatternResolver(BlobServiceClient blobServiceClient) {
this(blobServiceClient, null);
}
/**
* Constructor.
*
* @param shareServiceClient the ShareServiceClient.
*/
public AzureStorageResourcePatternResolver(ShareServiceClient shareServiceClient) {
this(null, shareServiceClient);
}
/**
* Constructor.
*
* @param blobServiceClient the BlobServiceClient.
* @param shareServiceClient the ShareServiceClient.
*/
public AzureStorageResourcePatternResolver(
BlobServiceClient blobServiceClient, ShareServiceClient shareServiceClient) {
this.blobServiceClient = Optional.ofNullable(blobServiceClient);
this.shareServiceClient = Optional.ofNullable(shareServiceClient);
}
/**
* @see ResourcePatternResolver#getResources(java.lang.String)
*/
@Override
public Resource[] getResources(String pattern) throws IOException {
Resource[] resources = null;
if (isAzureStorageResource(pattern, BLOB)) {
resources = getBlobResources(pattern);
} else if (isAzureStorageResource(pattern, FILE)) {
resources = getShareResources(pattern);
}
return resources;
}
/**
* @see ResourcePatternResolver#getResource(java.lang.String)
*/
@Override
public Resource getResource(String location) {
Resource resource = null;
if (isAzureStorageResource(location, BLOB) && blobServiceClient.isPresent()) {
resource = new BlobStorageResource(blobServiceClient.get(), location, true);
} else if (isAzureStorageResource(location, FILE) && shareServiceClient.isPresent()) {
resource = new FileStorageResource(shareServiceClient.get(), location, true);
}
return resource;
}
/**
* @see ResourcePatternResolver#getClassLoader()
*/
@Override
public ClassLoader getClassLoader() {
return getClass().getClassLoader();
}
/**
* Get the blob resources for the given pattern.
*
* @param pattern the pattern.
* @return the blob resources.
*/
private Resource[] getBlobResources(String pattern) {
ArrayList<Resource> resources = new ArrayList<>();
blobServiceClient.ifPresent(client -> {
Iterator<BlobContainerItem> containerIterator
= client.listBlobContainers().iterator();
while (containerIterator.hasNext()) {
BlobContainerItem containerItem = containerIterator.next();
String containerName = containerItem.getName();
BlobContainerClient blobContainerClient
= client.getBlobContainerClient(containerItem.getName());
Iterator<BlobItem> blobIterator = blobContainerClient.listBlobs().iterator();
while (blobIterator.hasNext()) {
BlobItem blobItem = blobIterator.next();
String blobName = blobItem.getName();
String location = "azure-blob://" + containerName + "/" + blobName;
if (matcher.match(pattern, location)) {
resources.add(new BlobStorageResource(client, location));
}
}
}
});
return resources.toArray(new Resource[]{});
}
/**
* Get the share resources for the given pattern.
*
* @param pattern the pattern.
* @return the share resources.
*/
private Resource[] getShareResources(String pattern) {
ArrayList<Resource> resources = new ArrayList<>();
shareServiceClient.ifPresent(client -> {
Iterator<ShareItem> shareIterator
= client.listShares().iterator();
while (shareIterator.hasNext()) {
ShareItem shareItem = shareIterator.next();
String shareName = shareItem.getName();
ShareClient shareClient
= client.getShareClient(shareItem.getName());
Iterator<ShareFileItem> shareFileIterator = shareClient
.getRootDirectoryClient().listFilesAndDirectories().iterator();
while (shareFileIterator.hasNext()) {
ShareFileItem fileItem = shareFileIterator.next();
String filename = fileItem.getName();
if (!fileItem.isDirectory()) {
String location = "azure-file://" + shareName + "/" + filename;
if (matcher.match(pattern, location)) {
resources.add(new FileStorageResource(client, location));
}
}
}
}
});
return resources.toArray(new Resource[]{});
}
}

Просмотреть файл

@ -0,0 +1,211 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.cloud.storage;
import com.azure.core.http.rest.PagedIterable;
import com.azure.storage.blob.BlobClient;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.models.BlobContainerItem;
import com.azure.storage.blob.models.BlobItem;
import com.azure.storage.blob.specialized.BlockBlobClient;
import com.azure.storage.file.share.ShareClient;
import com.azure.storage.file.share.ShareDirectoryClient;
import com.azure.storage.file.share.ShareServiceClient;
import com.azure.storage.file.share.models.ShareFileItem;
import com.azure.storage.file.share.models.ShareItem;
import java.io.IOException;
import java.util.ArrayList;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
/**
* The JUnit tests for the AzureStorageResourcePatternResolver class.
*/
@SpringBootTest(properties = "spring.main.banner-mode=off")
@RunWith(SpringRunner.class)
public class AzureStorageResourcePatternResolverTest {
/**
* Stores the BlobServiceClient.
*/
@Autowired
private BlobServiceClient blobServiceClient;
/**
* Stores the ShareServiceClient.
*/
@Autowired
private ShareServiceClient shareServiceClient;
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(blobServiceClient);
assertNotNull(resolver.getResources("azure-blob://mycontainer/myblob"));
}
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources2() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(blobServiceClient);
assertNotNull(resolver.getResources("azure-blob://mycontainer/*"));
}
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources3() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(blobServiceClient);
assertNotNull(resolver.getResources("azure-blob://*/myblob"));
}
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources4() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(blobServiceClient);
assertNotNull(resolver.getResources("azure-blob://*/*"));
}
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources5() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(shareServiceClient);
assertNotNull(resolver.getResources("azure-file://myshare/myfile"));
}
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources6() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(shareServiceClient);
assertNotNull(resolver.getResources("azure-file://myshare/*"));
}
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources7() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(shareServiceClient);
assertNotNull(resolver.getResources("azure-file://*/myfile"));
}
/**
* Test getResources method.
*
* @throws IOException when an I/O error occurs.
*/
@Test
public void testGetResources8() throws IOException {
AzureStorageResourcePatternResolver resolver
= new AzureStorageResourcePatternResolver(shareServiceClient);
assertNotNull(resolver.getResources("azure-file://*/*"));
}
@Configuration
@Import(AzureStorageProtocolResolver.class)
static class StorageApplication {
@Bean
public BlobServiceClient getBlobServiceClient() {
BlobServiceClient client = mock(BlobServiceClient.class);
PagedIterable<BlobContainerItem> blobContainerItems = mock(PagedIterable.class);
BlobContainerClient containerClient = mock(BlobContainerClient.class);
PagedIterable<BlobItem> blobItems = mock(PagedIterable.class);
BlobClient blobClient = mock(BlobClient.class);
BlockBlobClient blockBlobClient = mock(BlockBlobClient.class);
BlobContainerItem containerItem1 = new BlobContainerItem();
containerItem1.setName("mycontainer");
ArrayList containerList = new ArrayList<BlobContainerItem>();
containerList.add(containerItem1);
BlobItem blobItem1 = new BlobItem();
blobItem1.setName("myblob");
ArrayList blobList = new ArrayList<>();
blobList.add(blobItem1);
when(client.listBlobContainers()).thenReturn(blobContainerItems);
when(blobContainerItems.iterator()).thenReturn(containerList.iterator());
when(client.getBlobContainerClient("mycontainer")).thenReturn(containerClient);
when(containerClient.listBlobs()).thenReturn(blobItems);
when(blobItems.iterator()).thenReturn(blobList.iterator());
when(client.getBlobContainerClient("mycontainer")).thenReturn(containerClient);
when(containerClient.getBlobClient("myblob")).thenReturn(blobClient);
when(blobClient.getBlockBlobClient()).thenReturn(blockBlobClient);
return client;
}
@Bean
public ShareServiceClient getShareServiceClient() {
ShareServiceClient client = mock(ShareServiceClient.class);
PagedIterable<ShareItem> shareItems = mock(PagedIterable.class);
ShareClient shareClient = mock(ShareClient.class);
ShareDirectoryClient shareDirectoryClient = mock(ShareDirectoryClient.class);
PagedIterable<ShareFileItem> shareFileItems = mock(PagedIterable.class);
ShareItem shareItem1 = new ShareItem();
shareItem1.setName("myshare");
ArrayList shareList = new ArrayList<ShareItem>();
shareList.add(shareItem1);
ShareFileItem shareFileItem1 = new ShareFileItem("myfile", false, 0L);
ArrayList shareFileList = new ArrayList<ShareFileItem>();
shareFileList.add(shareFileItem1);
when(client.listShares()).thenReturn(shareItems);
when(shareItems.iterator()).thenReturn(shareList.iterator());
when(client.getShareClient("myshare")).thenReturn(shareClient);
when(shareClient.getRootDirectoryClient()).thenReturn(shareDirectoryClient);
when(shareDirectoryClient.listFilesAndDirectories()).thenReturn(shareFileItems);
when(shareFileItems.iterator()).thenReturn(shareFileList.iterator());
return client;
}
}
}