/* * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 * (the "License"). You may not use this work except in compliance with the License, which is * available at www.apache.org/licenses/LICENSE-2.0 * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied, as more fully set forth in the License. * * See the NOTICE file distributed with this work for information regarding copyright ownership. */ package alluxio.underfs; import alluxio.AlluxioURI; import alluxio.collections.Pair; import alluxio.underfs.options.CreateOptions; import alluxio.underfs.options.DeleteOptions; import alluxio.underfs.options.ListOptions; import alluxio.underfs.options.MkdirsOptions; import alluxio.underfs.options.OpenOptions; import alluxio.util.io.PathUtils; import com.google.common.base.Preconditions; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Queue; import javax.annotation.concurrent.ThreadSafe; /** * A base abstract {@link UnderFileSystem}. */ @ThreadSafe public abstract class BaseUnderFileSystem implements UnderFileSystem { /** The UFS {@link AlluxioURI} used to create this {@link BaseUnderFileSystem}. */ protected final AlluxioURI mUri; /** UFS Configuration options. */ protected final UnderFileSystemConfiguration mUfsConf; /** * Constructs an {@link BaseUnderFileSystem}. * * @param uri the {@link AlluxioURI} used to create this ufs * @param ufsConf UFS configuration */ protected BaseUnderFileSystem(AlluxioURI uri, UnderFileSystemConfiguration ufsConf) { mUri = Preconditions.checkNotNull(uri); mUfsConf = Preconditions.checkNotNull(ufsConf); } @Override public OutputStream create(String path) throws IOException { return create(path, CreateOptions.defaults().setCreateParent(true)); } @Override public boolean deleteDirectory(String path) throws IOException { return deleteDirectory(path, DeleteOptions.defaults()); } @Override public boolean exists(String path) throws IOException { return isFile(path) || isDirectory(path); } @Override public UfsStatus[] listStatus(String path, ListOptions options) throws IOException { if (!options.isRecursive()) { return listStatus(path); } path = validatePath(path); List<UfsStatus> returnPaths = new ArrayList<>(); // Each element is a pair of (full path, UfsStatus) Queue<Pair<String, UfsStatus>> pathsToProcess = new ArrayDeque<>(); // We call list initially, so we can return null if the path doesn't denote a directory UfsStatus[] statuses = listStatus(path); if (statuses == null) { return null; } else { for (UfsStatus status : statuses) { pathsToProcess.add(new Pair<>(PathUtils.concatPath(path, status.getName()), status)); } } while (!pathsToProcess.isEmpty()) { final Pair<String, UfsStatus> pathToProcessPair = pathsToProcess.remove(); final String pathToProcess = pathToProcessPair.getFirst(); UfsStatus pathStatus = pathToProcessPair.getSecond(); returnPaths.add(pathStatus.setName(pathToProcess.substring(path.length() + 1))); if (pathStatus.isDirectory()) { // Add all of its subpaths UfsStatus[] children = listStatus(pathToProcess); if (children != null) { for (UfsStatus child : children) { pathsToProcess.add( new Pair<>(PathUtils.concatPath(pathToProcess, child.getName()), child)); } } } } return returnPaths.toArray(new UfsStatus[returnPaths.size()]); } @Override public InputStream open(String path) throws IOException { return open(path, OpenOptions.defaults()); } @Override public boolean mkdirs(String path) throws IOException { return mkdirs(path, MkdirsOptions.defaults()); } @Override public AlluxioURI resolveUri(AlluxioURI ufsBaseUri, String alluxioPath) { return new AlluxioURI(ufsBaseUri.getScheme(), ufsBaseUri.getAuthority(), PathUtils.concatPath(ufsBaseUri.getPath(), alluxioPath), ufsBaseUri.getQueryMap()); } /** * Clean the path by creating a URI and turning it back to a string. * * @param path the path to validate * @return validated path */ protected static String validatePath(String path) { return new AlluxioURI(path).toString(); } }