All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.foreach.common.filemanager.services.AzureFolderResource Maven / Gradle / Ivy

/*
 * Copyright 2014 the original author or authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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.foreach.common.filemanager.services;

import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.models.BlobItem;
import com.azure.storage.blob.specialized.BlockBlobClient;
import com.foreach.common.filemanager.business.*;
import lombok.NonNull;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.AntPathMatcher;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiPredicate;

public class AzureFolderResource implements FolderResource
{
	private final FolderDescriptor descriptor;
	private final BlobServiceClient blobServiceClient;
	private final String containerName;
	private final String directoryName;

	public AzureFolderResource( @NonNull FolderDescriptor descriptor,
	                            @NonNull BlobServiceClient blobServiceClient,
	                            @NonNull String containerName,
	                            @NonNull String directoryName ) {
		this.descriptor = descriptor;
		this.blobServiceClient = blobServiceClient;
		this.containerName = containerName;
		this.directoryName = directoryName;
	}

	@Override
	public FolderDescriptor getDescriptor() {
		return descriptor;
	}

	@Override
	public Optional getParentFolderResource() {
		return descriptor.getParentFolderDescriptor()
		                 .map( fd -> new AzureFolderResource( fd, blobServiceClient, containerName, extractParentObjectName() ) );
	}

	@Override
	public FileRepositoryResource getResource( @NonNull String relativePath ) {
		if ( relativePath.isEmpty() || "/".equals( relativePath ) ) {
			return this;
		}

		if ( relativePath.endsWith( "/" ) ) {
			FolderDescriptor descriptor = this.descriptor.createFolderDescriptor( relativePath );
			String childPath = stripCurrentFolderId( descriptor.getFolderId() );
			String childObjectName = Paths.get( directoryName, childPath ) + "/";

			return new AzureFolderResource( descriptor, blobServiceClient, containerName, childObjectName );
		}

		FileDescriptor descriptor = this.descriptor.createFileDescriptor( relativePath );
		String childPath = stripCurrentFolderId( descriptor.getFolderId() );
		String childObjectName = Paths.get( directoryName, childPath, descriptor.getFileId() ).toString();

		return new AzureFileResource( descriptor, blobServiceClient, containerName, childObjectName );
	}

	@Override
	public Collection findResources( @NonNull String pattern ) {
		Set resources = new LinkedHashSet<>();
		AntPathMatcher pathMatcher = new AntPathMatcher( "/" );
		String p = StringUtils.startsWith( pattern, "/" ) ? pattern.substring( 1 ) : pattern;
		boolean matchOnlyDirectories = StringUtils.endsWith( p, "/" );

		if ( matchOnlyDirectories ) {
			p = p.substring( 0, p.length() - 1 );
		}

		BiPredicate keyMatcher = ( candidateObjectName, antPattern ) -> {
			if ( pathMatcher.match( antPattern, antPattern.endsWith( "/" ) ? candidateObjectName : StringUtils.removeEnd( candidateObjectName, "/" ) ) ) {
				return !matchOnlyDirectories || candidateObjectName.endsWith( "/" );
			}
			return false;
		};

		addAllMatchingResources( directoryName, resources, keyMatcher, p );
		return resources;
	}

	@SneakyThrows
	private void addAllMatchingResources( String prefix,
	                                      Collection resources,
	                                      BiPredicate keyMatcher,
	                                      String pattern ) {
		for ( BlobItem candidate : blobServiceClient.getBlobContainerClient( containerName ).listBlobsByHierarchy( prefix ) ) {
			BlockBlobClient listedBlob = blobServiceClient.getBlobContainerClient( containerName )
			                                              .getBlobClient( candidate.getName() )
			                                              .getBlockBlobClient();
			String objectName = listedBlob.getBlobName();
			if ( candidate.isPrefix() ) {
				if ( keyMatcher.test( objectName, directoryName + pattern ) ) {
					resources.add( buildResourceFromListBlobItem( candidate, objectName ) );
				}
				if ( keyMatcher.test( objectName, directoryName + getRootPattern( pattern ) ) ) {
					addAllMatchingResources( objectName, resources, keyMatcher, pattern );
				}
			}
			else {
				if ( !objectName.equals( directoryName ) && !objectName.endsWith( "/" ) && keyMatcher.test( objectName, directoryName + pattern ) ) {
					resources.add( buildResourceFromListBlobItem( candidate, objectName ) );
				}
			}
		}
	}

	private String getRootPattern( String pattern ) {
		if ( pattern.contains( "/" ) ) {
			return pattern.substring( 0, pattern.lastIndexOf( '/' ) );
		}
		return pattern;
	}

	private FileRepositoryResource buildResourceFromListBlobItem( BlobItem candidate, String objectName ) {
		String path = StringUtils.removeStart( objectName, directoryName );
		if ( candidate.isPrefix() ) {
			return new AzureFolderResource( descriptor.createFolderDescriptor( path ), blobServiceClient, containerName, objectName );
		}
		else {
			return new AzureFileResource( descriptor.createFileDescriptor( path ), blobServiceClient, containerName, objectName );
		}
	}

	@Override
	public boolean delete( boolean deleteChildren ) {
		boolean deleted = false;
		if ( deleteChildren ) {
			deleted = deleteChildren();
		}
		if ( isNotRootFolder() ) {
			deleted = true;
		}
		return deleted;
	}

	@Override
	public boolean deleteChildren() {
		Collection resources = findResources( "*" );
		if ( !resources.isEmpty() ) {
			resources.forEach( r -> {
				if ( r instanceof FileResource ) {
					( (FileResource) r ).delete();
				}
				else {
					( (FolderResource) r ).delete( true );
				}
			} );
			return true;
		}
		return false;
	}

	@Override
	public boolean create() {
		return isNotRootFolder();
	}

	@Override
	public boolean exists() {
		return true;
	}

	@Override
	public boolean equals( Object o ) {
		if ( this == o ) {
			return true;
		}
		return o != null && ( o instanceof FolderResource && descriptor.equals( ( (FolderResource) o ).getDescriptor() ) );
	}

	@Override
	public int hashCode() {
		return descriptor.hashCode();
	}

	@Override
	public String toString() {
		return "axfs [" + descriptor + "] -> "
				+ String.format( "Azure storage blob resource[container='%s', blob='%s']", containerName, directoryName );
	}

	private String stripCurrentFolderId( String folderId ) {
		return StringUtils.defaultString( descriptor.getFolderId() != null
				                                  ? StringUtils.removeStart( folderId, descriptor.getFolderId() )
				                                  : folderId );
	}

	private String extractParentObjectName() {
		Path parent = Paths.get( directoryName ).getParent();
		return parent != null ? parent.toString().replaceAll( "\\\\", "/" ) + "/" : "";
	}

	private boolean isNotRootFolder() {
		return !"".equals( directoryName );
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy