AzureStorageResourcePatternResolver.java
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.spring.autoconfigure.storage.resource;
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 org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.AntPathMatcher;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Optional;
/**
* 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 final Optional<BlobServiceClient> blobServiceClient;
/**
* Stores the ShareServiceClient shareServiceClient
*/
private final 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 (AzureStorageUtils.isAzureStorageResource(pattern, StorageType.BLOB)) {
resources = getBlobResources(pattern);
} else if (AzureStorageUtils.isAzureStorageResource(pattern, StorageType.FILE)) {
resources = getShareResources(pattern);
}
if (null == resources) {
throw new IOException("Resources not found at " + pattern);
}
return resources;
}
/**
* @see ResourcePatternResolver#getResource(java.lang.String)
*/
@Override
public Resource getResource(String location) {
Resource resource = null;
if (AzureStorageUtils.isAzureStorageResource(location, StorageType.BLOB) && blobServiceClient.isPresent()) {
resource = new BlobStorageResource(blobServiceClient.get(), location, true);
} else if (AzureStorageUtils.isAzureStorageResource(location, StorageType.FILE)
&& shareServiceClient.isPresent()) {
resource = new FileStorageResource(shareServiceClient.get(), location, true);
}
if (null == resource) {
throw new IllegalArgumentException("Resource not found at " + location);
}
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[]{});
}
}