* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#include "proxy_filesystem.h"
#include <algorithm>
#include <cstring>
#include <base/containers/iterator.h>
#include <base/containers/string.h>
#include <base/containers/string_view.h>
#include <base/containers/type_traits.h>
#include <base/containers/unique_ptr.h>
#include <base/containers/vector.h>
#include <base/namespace.h>
#include <core/io/intf_directory.h>
#include <core/io/intf_file.h>
#include <core/namespace.h>
#include "file_manager.h"
#include "path_tools.h"
#include "proxy_directory.h"
CORE_BEGIN_NAMESPACE()
using BASE_NS::move;
using BASE_NS::string;
using BASE_NS::string_view;
using BASE_NS::vector;
ProxyFilesystem::ProxyFilesystem(FileManager& fileManager, const string_view destination)
: fileManager_(fileManager), destinations_()
{
AppendSearchPath(destination);
}
void ProxyFilesystem::AppendSearchPath(string_view path)
{
if (path.empty()) {
return;
}
if (path.back() == '/') {
path.remove_suffix(1);
}
destinations_.emplace_back(path);
}
void ProxyFilesystem::PrependSearchPath(string_view path)
{
if (path.empty()) {
return;
}
if (path.back() == '/') {
path.remove_suffix(1);
}
destinations_.emplace(destinations_.begin(), path);
}
void ProxyFilesystem::RemoveSearchPath(string_view destination)
{
if (destination.empty()) {
return;
}
if (destination.back() == '/') {
destination.remove_suffix(1);
}
const auto it = std::find(destinations_.cbegin(), destinations_.cend(), destination);
if (it != destinations_.cend()) {
destinations_.erase(it);
}
}
IDirectory::Entry ProxyFilesystem::GetEntry(const string_view path)
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
auto file = fileManager_.GetEntry(destination + normalizedPath);
if (file.type != IDirectory::Entry::UNKNOWN) {
return file;
}
}
}
return {};
}
IFile::Ptr ProxyFilesystem::OpenFile(const string_view path, const IFile::Mode mode)
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
auto file = fileManager_.OpenFile(destination + normalizedPath, mode);
if (file) {
return file;
}
}
}
return {};
}
IFile::Ptr ProxyFilesystem::CreateFile(const string_view path)
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
auto file = fileManager_.CreateFile(destination + normalizedPath);
if (file) {
return file;
}
}
}
return {};
}
bool ProxyFilesystem::DeleteFile(const string_view path)
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
if (fileManager_.DeleteFile(destination + normalizedPath)) {
return true;
}
}
}
return false;
}
bool ProxyFilesystem::FileExists(const string_view path) const
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
if (fileManager_.FileExists(destination + normalizedPath)) {
return true;
}
}
}
return false;
}
IDirectory::Ptr ProxyFilesystem::OpenDirectory(const string_view path)
{
IDirectory::Ptr proxyDirectory;
vector<IDirectory::Ptr> directories;
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
auto directory = fileManager_.OpenDirectory(destination + normalizedPath);
if (directory) {
directories.push_back(move(directory));
}
}
}
if (!directories.empty()) {
proxyDirectory.reset(new ProxyDirectory(move(directories)));
}
return proxyDirectory;
}
IDirectory::Ptr ProxyFilesystem::CreateDirectory(const string_view path)
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
auto directory = fileManager_.CreateDirectory(destination + normalizedPath);
if (directory) {
return directory;
}
}
}
return {};
}
bool ProxyFilesystem::DeleteDirectory(const string_view path)
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
if (fileManager_.DeleteDirectory(destination + normalizedPath)) {
return true;
}
}
}
return false;
}
bool ProxyFilesystem::DirectoryExists(const string_view path) const
{
auto normalizedPath = NormalizePath(path);
if (!normalizedPath.empty()) {
for (auto&& destination : destinations_) {
if (fileManager_.DirectoryExists(destination + normalizedPath)) {
return true;
}
}
}
return false;
}
bool ProxyFilesystem::Rename(const string_view fromPath, const string_view toPath)
{
if (!fromPath.empty() && !toPath.empty()) {
auto pathFrom = NormalizePath(fromPath);
auto pathTo = NormalizePath(toPath);
for (auto&& destination : destinations_) {
if (fileManager_.Rename(destination + pathFrom, destination + pathTo)) {
return true;
}
}
}
return false;
}
vector<string> ProxyFilesystem::GetUriPaths(const string_view uri) const
{
vector<string> paths;
auto path = NormalizePath(uri);
if (!path.empty()) {
for (auto&& destination : destinations_) {
auto directory = fileManager_.OpenDirectory(destination + path);
if (directory) {
paths.push_back(destination + path);
}
}
}
return paths;
}
CORE_END_NAMESPACE()