Android Open Source - android_device Storage Editor






From Project

Back to project page android_device.

License

The source code is released under:

[Apache License](http://www.apache.org/licenses/): Version 2.0, January 2004 =============== ## TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ## ### 1. Definitions. ### "License" sha...

If you think the Android project android_device listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * =================================================================================================
 *                    Copyright (C) 2014 Martin Albedinsky [Wolf-ITechnologies]
 * =================================================================================================
 *         Licensed under the Apache License, Version 2.0 or later (further "License" only).
 * -------------------------------------------------------------------------------------------------
 * You may use this file only in compliance with the License. More details and copy of this License 
 * you may obtain at//from w ww .ja  v  a2s  .co m
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * You can redistribute, modify or publish any part of the code written within this file but as it 
 * is described in the License, the software distributed under the License is distributed on an 
 * "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF ANY KIND.
 * 
 * See the License for the specific language governing permissions and limitations under the License.
 * =================================================================================================
 */
package com.wit.android.device.util;

import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <h3>Class Overview</h3>
 * todo: description
 *
 * @author Martin Albedinsky
 */
public class StorageEditor {

  /**
   * Interface ===================================================================================
   */

  /**
   * Constants ===================================================================================
   */

  /**
   * Log TAG.
   */
  private static final String TAG = "StorageEditor";

  /**
   * Flag indicating whether the output trough log-cat is enabled or not.
   */
  // private static final boolean LOG_ENABLED = true;

  /**
   * Flag indicating whether the debug output trough log-cat is enabled or not.
   */
  // private static final boolean DEBUG_ENABLED = true;

  /**
   * Flags ---------------------------------------------------------------------------------------
   */

  /**
   * Flag used to indicate that default options for storage operation should be used.
   */
  public static final int DEFAULT = 0x00;

  /**
   * Flag used to indicate that file/directory can be overwritten.
   */
  public static final int OVERWRITE = 0x01;

  /**
   * Flag used to indicate that copy of file/directory should be created with {@link #COPY_SUFFIX}.
   */
  public static final int COPY = 0x02;

  /**
   * ---------------------------------------------------------------------------------------------
   */

  /**
   * Small buffer type for {@link #createBuffer(int)} method.
   * <p>
   * Size of buffer: <b>512 bytes</b>
   */
  public static final int SMALL_BUFFER = 0x01;

  /**
   * Medium buffer type for {@link #createBuffer(int)} method.
   * <p>
   * Size of buffer: <b>1024 bytes</b>
   */
  public static final int MEDIUM_BUFFER = 0x02;

  /**
   * Large buffer type for {@link #createBuffer(int)} method.
   * <p>
   * Size of buffer: <b>2048 bytes</b>
   */
  public static final int LARGE_BUFFER = 0x04;

  /**
   * X-Large buffer type for {@link #createBuffer(int)} method.
   * <p>
   * Size of buffer: <b>4096 bytes</b>
   */
  public static final int XLARGE_BUFFER = 0x08;

  /**
   * XX-Large buffer type for {@link #createBuffer(int)} method.
   * <p>
   * Size of buffer: <b>8192 bytes</b>
   */
  public static final int XXLARGE_BUFFER = 0x10;

  /**
   * Suffix for name of file/directory when creating a copy of it passing {@link #COPY} flag to some
   * of this editor's methods accepting <b>flags</b> parameter.
   */
  public static final String COPY_SUFFIX = "-Copy";

  /**
   * Base size for bytes buffer.
   */
  private static final int BASE_BUFFER_SIZE = 512;

  /**
   * Static members ==============================================================================
   */

  /**
   * Matcher to match file name and extract its type.
   */
  private static final Matcher FILE_NAME_MATCHER = Pattern.compile("^(.*)\\.(.+)$").matcher("");

  /**
   * Members =====================================================================================
   */

  /**
   * Constructors ================================================================================
   */

  /**
   * Methods =====================================================================================
   */

  /**
   * Public --------------------------------------------------------------------------------------
   */

  /**
   * Creates a new <b>bytes</b> buffer for the specified <var>bufferType</var>.
   *
   * @param bufferType Type of buffer to create. One of {@link #SMALL_BUFFER}, {@link #MEDIUM_BUFFER},
   *                   {@link #LARGE_BUFFER}, {@link #XLARGE_BUFFER}, {@link #XXLARGE_BUFFER}.
   * @return New bytes buffer with size of the requested type or size of <b>1024</b> if there is no
   * such a buffer type.
   */
  @NonNull
  public static byte[] createBuffer(int bufferType) {
    switch (bufferType) {
      case SMALL_BUFFER:
      case MEDIUM_BUFFER:
      case LARGE_BUFFER:
      case XLARGE_BUFFER:
      case XXLARGE_BUFFER:
        return new byte[bufferType * BASE_BUFFER_SIZE];
    }
    return new byte[1024];
  }

  /**
   * Same as {@link #deleteDirectory(java.io.File, java.io.FileFilter, java.io.FilenameFilter)}
   * with {@code null} filters.
   */
  public boolean deleteDirectory(@NonNull File directory) {
    return deleteDirectory(directory, null, null);
  }

  /**
   * Deletes the given directory and its content (all files + subdirectories) on the file system.
   *
   * @param directory  The desired directory to delete.
   * @param filter     The filter used to delete only desired files form the requested directory.
   *                   Pass {@code null} to delete all files.
   * @param nameFilter The filter used to delete only files with desired names form the requested
   *                   directory. Pass {@code null} to delete all files.
   * @return {@code True} if directory was successfully deleted, {@code false} otherwise.
   */
  public boolean deleteDirectory(@NonNull File directory, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter) {
    synchronized (StorageEditor.class) {
      return directory.isDirectory() && this.deleteDirectoryContentInner(directory, filter, nameFilter);
    }
  }

  /**
   * Same as {@link #copyFileContent(int, java.io.File, java.io.File)} with {@link #COPY} flag and
   * {@code null} <var>toFile</var> parameter, so there will be created new copy of the given
   * <var>file</var> at the same path with {@link #COPY_SUFFIX}.
   */
  public boolean copyFileContent(@NonNull File file) throws IOException {
    return copyFileContent(COPY, file, null);
  }

  /**
   * Copies a content from the given <var>fromFile</var> into the given <var>toFile</var>.
   *
   * @param flags    The flags used manage move process. See {@link #OVERWRITE}, {@link #COPY}.
   * @param fromFile The desired file of which content to copy.
   * @param toFile   The desired file to which should be content of the requested file copied.
   * @return {@code True} if file was successfully copied, {@code false} if some error
   * occurs during copy process or the given flags were not properly specified.
   * @throws FileNotFoundException    If the given <var>fromFile</var> doesn't exists or is not a file.
   * @throws IllegalArgumentException If the given <var>toFile</var> is not a file but a directory.
   * @throws IOException              If some IO error occurs during copy process of the requested file.
   */
  public boolean copyFileContent(int flags, @NonNull File fromFile, @Nullable File toFile) throws IOException {
    if (!fromFile.isFile()) {
      throw new FileNotFoundException(
          "Can not to copy content of file(" + fromFile.getPath() + "). Such a file doesn't exists or it is a directory."
      );
    }
    if (toFile != null && toFile.isDirectory()) {
      throw new IllegalArgumentException(
          "Can not to copy content to file(" + toFile.getPath() + "). Destination already exists and it is a directory not a file."
      );
    }
    return this.copyFileContentInner(flags, fromFile, toFile);
  }

  /**
   * Same as {@link #copyDirectoryContent(int, java.io.File, java.io.File)} with {@link #COPY} flag
   * and {@code null} <var>toDirectory</var> parameter, so there will be created new copy of
   * the given <var>directory</var> at the same path with {@link #COPY_SUFFIX}.
   */
  public boolean copyDirectoryContent(@NonNull File directory) throws IOException {
    return copyDirectoryContent(COPY, directory, null);
  }

  /**
   * Same as {@link #copyDirectoryContent(int, java.io.File, java.io.File, java.io.FileFilter, java.io.FilenameFilter)}
   * with {@code null} filters.
   */
  public boolean copyDirectoryContent(int flags, @NonNull File fromDirectory, @Nullable File toDirectory) throws IOException {
    return copyDirectoryContent(flags, fromDirectory, toDirectory, null, null);
  }

  /**
   * Copies a content from the given <var>fromDirectory</var> into the given <var>toDirectory</var>.
   *
   * @param flags         The flags used manage copy process. See {@link #OVERWRITE}, {@link #COPY}.
   * @param fromDirectory The desired directory of which content to copy.
   * @param toDirectory   The desired directory to which should be content of the requested directory
   *                      copied.
   * @param filter        The filter used to copy only desired files form the requested directory.
   *                      Pass {@code null} to copy all files.
   * @param nameFilter    The filter used to copy only files with desired names form the requested
   *                      directory. Pass {@code null} to copy all files.
   * @return {@code True} if directory was successfully copied, {@code false} if some error
   * occurs during copy process or the given flags were not properly specified.
   * @throws FileNotFoundException    If the given <var>fromDirectory</var> doesn't exists or is not a directory.
   * @throws IllegalArgumentException If the given <var>toDirectory</var> is not a directory but a file.
   * @throws IOException              If some IO error occurs during copy process of the requested file.
   */
  public boolean copyDirectoryContent(int flags, @NonNull File fromDirectory, @Nullable File toDirectory, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter) throws IOException {
    if (!fromDirectory.isDirectory()) {
      throw new FileNotFoundException(
          "Can not to copy content of directory(" + fromDirectory.getPath() + "). Such a directory doesn't exists or it is a file."
      );
    }
    if (toDirectory != null && toDirectory.isFile()) {
      throw new IllegalArgumentException(
          "Can not to copy content to directory(" + toDirectory.getPath() + "). Destination already exists and it is a file not a directory."
      );
    }
    return this.copyDirectoryContentInner(flags, fromDirectory, toDirectory, filter, nameFilter);
  }

  /**
   * Moves a content from the given <var>fromFile</var> into the given <var>toFile</var>. When content
   * is successfully moved, the file, from which was content moved, is deleted.
   * <p>
   * This implementation actually moves content between the given files and than deletes the old one.
   *
   * @param flags    The flags used manage move process. See {@link #OVERWRITE}, {@link #COPY}.
   * @param fromFile The desired file of which content to move.
   * @param toFile   The desired file to which should be content of the requested file moved.
   * @return {@code True} if file was successfully moved and old one deleted, {@code false}
   * if some error occurs during move process or the given flags were not properly specified.
   * @throws FileNotFoundException    If the given <var>fromFile</var> doesn't exists or is not a file.
   * @throws IllegalArgumentException If the given <var>toFile</var> is not a file but a directory.
   * @throws IOException              If some IO error occurs during copy process of the requested file.
   */
  public boolean moveFileContent(int flags, @NonNull File fromFile, @Nullable File toFile) throws IOException {
    if (!fromFile.isFile()) {
      throw new FileNotFoundException(
          "Can not to move content of file(" + fromFile.getPath() + "). Such a file doesn't exists or it is a directory."
      );
    }
    if (toFile != null && toFile.isDirectory()) {
      throw new IllegalArgumentException(
          "Can not to move content to file(" + toFile.getPath() + "). Destination already exists and it is a directory not a file."
      );
    }
    return this.moveFileContentInner(flags, fromFile, toFile);
  }

  /**
   * Same as {@link #moveDirectoryContent(int, java.io.File, java.io.File, java.io.FileFilter, java.io.FilenameFilter)}
   * with {@code null} filters.
   */
  public boolean moveDirectoryContent(int flags, @NonNull File fromDirectory, @Nullable File toDirectory) throws IOException {
    return moveDirectoryContent(flags, fromDirectory, toDirectory, null, null);
  }

  /**
   * Moves a content (files + subdirectories) from the given <var>fromDirectory</var> into the given
   * <var>toDirectory</var>. When content is successfully moved, the directory, from which was content
   * moved, is deleted.
   * <p>
   * This implementation actually moves content between the given directories and than deletes the
   * old one.
   *
   * @param flags         The flags used manage move process. See {@link #OVERWRITE}, {@link #COPY}.
   * @param fromDirectory The desired directory of which content to move.
   * @param toDirectory   The desired directory to which should be content of the requested directory
   *                      moved.
   * @param filter        The filter used to move only desired files form the requested directory.
   *                      Pass {@code null} to move all files.
   * @param nameFilter    The filter used to move only files with desired names form the requested
   *                      directory. Pass {@code null} to move all files.
   * @return {@code True} if directory was successfully moved and old one deleted, {@code false}
   * if some error occurs during move process or the given flags were not properly specified.
   * @throws FileNotFoundException         If the given <var>fromDirectory</var> doesn't exists or is not a directory.
   * @throws IllegalArgumentException      If the given <var>toDirectory</var> is not a directory but a file.
   * @throws UnsupportedOperationException
   * @throws IOException                   If some IO error occurs during copy process of the requested file.
   */
  public boolean moveDirectoryContent(int flags, @NonNull File fromDirectory, @Nullable File toDirectory, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter) throws IOException {
    if (!fromDirectory.isDirectory()) {
      throw new FileNotFoundException(
          "Can not to move content of directory(" + fromDirectory.getPath() + "). Such a directory doesn't exists or it is a file."
      );
    }
    if (toDirectory != null) {
      if (toDirectory.isFile()) {
        throw new IllegalArgumentException(
            "Can not to move content to directory(" + toDirectory.getPath() + "). Destination already exists and it is a file not a directory."
        );
      }
      // Check if there is request to move directory to itself, that's not supported.
      final File parent = toDirectory.getParentFile();
      final String directoryPath = fromDirectory.getPath();
      if (parent != null && directoryPath.equals(parent.getPath())) {
        throw new UnsupportedOperationException("Can not to move directory('" + directoryPath + "') to itself.");
      }
    }
    return this.moveDirectoryContentInner(flags, fromDirectory, toDirectory, filter, nameFilter);
  }

  /**
   * Same as {@link #copyFileStreams(java.io.FileInputStream, java.io.FileOutputStream, int)}
   * with {@link #MEDIUM_BUFFER} type.
   */
  public boolean copyFileStreams(@NonNull FileInputStream inputStream, @NonNull FileOutputStream outputStream) throws IOException {
    return copyFileStreams(inputStream, outputStream, MEDIUM_BUFFER);
  }

  /**
   * Same as {@link #copyFileStreams(java.io.FileInputStream, java.io.FileOutputStream, byte[])}
   * with buffer obtained from {@link #createBuffer(int)} for the desired <var>bufferType</var>.
   */
  public boolean copyFileStreams(@NonNull FileInputStream inputStream, @NonNull FileOutputStream outputStream, int bufferType) throws IOException {
    return copyFileStreams(inputStream, outputStream, createBuffer(bufferType));
  }

  /**
   * Copies a content of the given <var>inputStream</var> into the given <var>outputStream</var>
   * using the given <var>buffer</var>.
   * <p>
   * <b>Note</b>, that if the IOException occurs, the given streams will be not closed by this implementation,
   * so it is your duty to close them in <b>finally</b> block of your <b>try catch</b> statement.
   *
   * @param inputStream  The input stream of which content to copy.
   * @param outputStream The output stream where should be content copied.
   * @param buffer       Buffer used for copy process. Larger buffer will make copy process faster,
   *                     but also more memory intensive.
   * @return Always {@code true} if no IOException is thrown.
   * @throws IOException If some input/output error occurs during copy process.
   */
  public boolean copyFileStreams(@NonNull FileInputStream inputStream, @NonNull FileOutputStream outputStream, byte[] buffer) throws IOException {
    int bytes;
    while ((bytes = inputStream.read(buffer, 0, buffer.length)) > 0) {
      outputStream.write(buffer, 0, bytes);
    }
    inputStream.close();
    outputStream.close();
    return true;
  }

  /**
   * Getters + Setters ---------------------------------------------------------------------------
   */

  /**
   * Protected -----------------------------------------------------------------------------------
   */

  /**
   * Private -------------------------------------------------------------------------------------
   */

  /**
   * Deletes the given directory and its content on the file system.
   *
   * @param directory  The desired directory to delete.
   * @param filter     The filter used to delete only desired files form the requested directory.
   * @param nameFilter The filter used to delete only files with desired names form the requested
   *                   directory.
   * @return {@code True} if content and the given directory was successfully deleted,
   * {@code false} if some error occurs during delete process.
   */
  private boolean deleteDirectoryContentInner(File directory, FileFilter filter, FilenameFilter nameFilter) {
    final File[] files = directory.listFiles();
    boolean isDir;
    boolean failed = false;
    if (files.length > 0) {
      for (File file : files) {
        // Apply filters.
        if ((filter != null && !filter.accept(file)) || (nameFilter != null && !nameFilter.accept(file, file.getName()))) {
          continue;
        }
        // File passed through filters, resolve how to delete it.
        isDir = file.isDirectory();
        if (isDir && !deleteDirectoryContentInner(file, filter, nameFilter)) {
          logError("Failed to delete directory('" + file.getName() + "').");
          failed = true;
        } else if (!isDir && !file.delete()) {
          logError("Failed to delete file('" + file.getName() + "').");
          failed = true;
        }
      }
    }
    if (directory.listFiles().length == 0) {
      // Apply filters.
      if ((filter == null && nameFilter == null) || (filter != null && filter.accept(directory)) || (nameFilter != null && nameFilter.accept(directory, directory.getName()))) {
        if (!directory.delete()) {
          failed = true;
        }
      }
    }
    return !failed;
  }

  /**
   * Copies the given file and its content on the file system.
   *
   * @param flags    The flags used manage copy process.
   * @param fromFile The desired file of which content to copy.
   * @param toFile   The desired file to which should be content of the requested file copied.
   * @return {@code True} if content of the requested file was successfully copied,
   * {@code false} if some error occurs during copy process or the given flags were not properly
   * specified.
   */
  private boolean copyFileContentInner(int flags, File fromFile, File toFile) throws IOException {
    synchronized (StorageEditor.class) {
      String toFilePath = toFile != null ? toFile.getPath() : "";
      if (TextUtils.isEmpty(toFilePath)) {
        if ((flags & COPY) == 0) {
          logError("Failed to copy content of file('" + fromFile.getPath() + "') without StorageEditor.COPY flag. Such a file already exists.");
          return false;
        }
        // Append -Copy suffix to file path.
        toFilePath = appendPath(fromFile, COPY_SUFFIX).getPath();
      } else if (toFile != null && toFile.exists()) {
        final boolean copy = (flags & COPY) != 0;
        final boolean overwrite = (flags & OVERWRITE) != 0;
        if (!copy && !overwrite) {
          logError("Failed to copy content to file('" + toFilePath + "') without StorageEditor.COPY or StorageEditor.OVERWRITE flag. Such a file already exists.");
          return false;
        } else if (copy) {
          // Append -Copy suffix to file path.
          toFilePath = appendPath(toFile, COPY_SUFFIX).getPath();
        } else {
          // Do not overwrite existing file.
          return false;
        }
      }

      if ((toFile = createAndGetFile(toFilePath)) == null) {
        return false;
      }

      final FileInputStream input = new FileInputStream(fromFile);
      final FileOutputStream output = new FileOutputStream(toFile);
      copyFileStreams(input, output);
      input.close();
      output.close();
      return true;
    }
  }

  /**
   * Copies the given directory and its content on the file system.
   *
   * @param flags         The flags used manage copy process.
   * @param fromDirectory The desired directory of which content to copy.
   * @param toDirectory   The desired directory to which should be content of the requested directory
   *                      copied.
   * @param filter        The filter used to copy only desired files form the requested directory.
   * @param nameFilter    The filter used to copy only files with desired names form the requested
   *                      directory.
   * @return {@code True} if content of the requested directory was successfully copied,
   * {@code false} if some error occurs during copy process or the given flags were not properly
   * specified.
   */
  private boolean copyDirectoryContentInner(int flags, File fromDirectory, File toDirectory, FileFilter filter, FilenameFilter nameFilter) throws IOException {
    final File[] files = fromDirectory.listFiles();
    String toDirectoryPath = toDirectory != null ? toDirectory.getPath() : "";
    boolean failed = false;
    if (files.length > 0) {
      File tempFile;
      synchronized (StorageEditor.class) {
        for (File file : files) {
          // Apply filters.
          if ((filter != null && !filter.accept(file)) || (nameFilter != null && !nameFilter.accept(file, file.getName()))) {
            continue;
          }
          // File passed through filters, resolve how to copy it.
          tempFile = new File(appendPathWithFilename(toDirectoryPath, file.getName()));
          if (file.isDirectory()) {
            if (copyDirectoryContentInner(flags, file, tempFile, filter, nameFilter)) {
              continue;
            }
            logError("Failed to copy content of directory('" + file.getPath() + "').");
            failed = true;
          } else if (file.isFile()) {
            if (copyFileContentInner(flags, file, tempFile)) {
              continue;
            }
            logError("Failed to copy content of file('" + file.getPath() + "').");
            failed = true;
          }
        }
      }
    } else {
      synchronized (StorageEditor.class) {
        if (TextUtils.isEmpty(toDirectoryPath)) {
          if ((flags & COPY) == 0) {
            logError("Failed to copy content of directory('" + fromDirectory.getPath() + "') without StorageEditor.COPY flag. Such a directory already exists.");
            failed = true;
          } else {
            // Append -Copy suffix to directory path.
            toDirectoryPath = appendPath(fromDirectory, COPY_SUFFIX).getPath();
          }
        } else if (toDirectory != null && toDirectory.exists()) {
          if ((flags & COPY) == 0) {
            logError("Failed to copy content to directory('" + toDirectoryPath + "') without StorageEditor.COPY flag. Such a directory already exists.");
            failed = true;
          } else {
            // Append -Copy suffix to directory path.
            toDirectoryPath = appendPath(toDirectory, COPY_SUFFIX).getPath();
          }
        }

        if (!failed) {
          final File toDir = new File(toDirectoryPath);
          // Apply filters.
          if ((filter != null && !filter.accept(toDir)) || (nameFilter != null && !nameFilter.accept(toDir, toDir.getName()))) {
            return true;
          }
          // Directory passed through filters.
          if (!toDir.exists() && !createDirectory(toDirectoryPath)) {
            logError("Failed to create directory('" + toDirectoryPath + "').");
            failed = true;
          }
        }
      }
    }
    return !failed;
  }

  /**
   * Moves the given file and its content on the file system.
   *
   * @param flags    The flags used manage move process.
   * @param fromFile The desired file of which content to move.
   * @param toFile   The desired file to which should be content of the requested file moved.
   * @return {@code True} if content of the requested file was successfully moved and old file
   * was deleted, {@code false} if some error occurs during move process or the given flags
   * were not properly specified.
   */
  private boolean moveFileContentInner(int flags, File fromFile, File toFile) throws IOException {
    return this.copyFileContentInner(flags, fromFile, toFile) && fromFile.delete();
  }

  /**
   * Moves the given directory and its content on the file system.
   *
   * @param flags         The flags used manage move process.
   * @param fromDirectory The desired directory of which content to move.
   * @param toDirectory   The desired directory to which should be content of the requested directory
   *                      moved.
   * @param filter        The filter used to move only desired files form the requested directory.
   * @param nameFilter    The filter used to move only files with desired names form the requested
   *                      directory.
   * @return {@code True} if content of the requested directory was successfully moved and the
   * old directory was deleted, {@code false} if some error occurs during move process or the
   * given flags were not properly specified.
   */
  private boolean moveDirectoryContentInner(int flags, File fromDirectory, File toDirectory, FileFilter filter, FilenameFilter nameFilter) throws IOException {
    return this.copyDirectoryContentInner(flags, fromDirectory, toDirectory, filter, nameFilter) && this.deleteDirectory(fromDirectory, filter, nameFilter);
  }

  /**
   * Creates and returns a new empty file at the specified <var>path</var>.
   *
   * @param path The desired path at which should be the requested file created.
   * @return {@code True} if file was successfully created or already exists, {@code false}
   * if some error occurs or there is already a directory at the specified path.
   */
  private static File createAndGetFile(String path) {
    final File file = new File(path);
    synchronized (StorageEditor.class) {
      if (file.isFile()) {
        return file;
      }

      if (!file.exists()) {
        // First check if all parent directories exists.
        final Uri fileUri = Uri.parse(path);
        final File parentDirs = new File(fileUri.getPath().replace(fileUri.getLastPathSegment(), ""));
        if ((!parentDirs.exists() || !parentDirs.isDirectory()) && !parentDirs.mkdirs()) {
          logError("Failed to create parent directories for file('" + path + "').");
          return null;
        }
        try {
          return file.createNewFile() ? file : null;
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      return null;
    }
  }

  /**
   * Creates a new empty directory at the specified <var>path</var>.
   *
   * @param path The desired path at which should be the requested directory created.
   * @return {@code True} if directory was successfully created or already exists, {@code false}
   * if some error occurs or there is already a file at the specified path.
   */
  private static boolean createDirectory(String path) {
    final File file = new File(path);
    synchronized (StorageEditor.class) {
      return file.isDirectory() || file.mkdirs();
    }
  }

  /**
   * Appends a path of the given <var>file</var> with the given <var>suffix</var>. If the given file
   * represents a file, the given suffix will be appended to last path segment of the given file's
   * path preserving its type at the end.
   *
   * @param file   The file of which path to append.
   * @param suffix The suffix which to add at the end of the given file's path.
   * @return New file with appended path.
   */
  private static File appendPath(File file, String suffix) {
    String filePath = file.getPath();
    if (TextUtils.isEmpty(filePath)) {
      return file;
    }

    if (file.isDirectory()) {
      return new File(filePath + suffix);
    }
    final String lastPathSegment = Uri.parse(filePath).getLastPathSegment();
    if (FILE_NAME_MATCHER.reset(lastPathSegment).matches()) {
      final String fileType = FILE_NAME_MATCHER.group(2);
      // Remove the type suffix from path.
      filePath = filePath.substring(0, filePath.length() - fileType.length() - 1);
      return new File(filePath + suffix + "." + fileType);
    }
    return file;
  }

  /**
   * Appends the given <var>path</var> with the given <var>filename</var>.
   *
   * @param path     The path which to append.
   * @param filename The name of file which to add at the end of the given path.
   * @return Appended path or <var>filename</var> if the given path is empty.
   */
  private static String appendPathWithFilename(String path, String filename) {
    return !TextUtils.isEmpty(path) ? path + File.separator + filename : "";
  }

  /**
   * Logs the given <var>errorMessage</var> with {@link android.util.Log#e(String, String)} with
   * this class's TAG.
   *
   * @param errorMessage The desired error message to log.
   */
  private static void logError(String errorMessage) {
    Log.e(TAG, errorMessage);
  }

  /**
   * Inner classes ===============================================================================
   */
}




Java Source Code List

com.wit.android.device.AndroidDevice.java
com.wit.android.device.BatteryImpl.java
com.wit.android.device.Battery.java
com.wit.android.device.ConnectionImpl.java
com.wit.android.device.Connection.java
com.wit.android.device.DeviceConfig.java
com.wit.android.device.ScreenImpl.java
com.wit.android.device.Screen.java
com.wit.android.device.StorageAction.java
com.wit.android.device.StorageImpl.java
com.wit.android.device.Storage.java
com.wit.android.device.examples.HomeActivity.java
com.wit.android.device.examples.adapter.BatteryInfoAdapter.java
com.wit.android.device.examples.adapter.ConnectionInfoAdapter.java
com.wit.android.device.examples.adapter.FilesAdapter.java
com.wit.android.device.examples.adapter.OrientationsAdapter.java
com.wit.android.device.examples.adapter.SimpleInfoAdapter.java
com.wit.android.device.examples.adapter.StorageAdapter.java
com.wit.android.device.examples.dialog.NewFileDialog.java
com.wit.android.device.examples.fragment.BaseDeviceFragment.java
com.wit.android.device.examples.fragment.BatteryInfoFragment.java
com.wit.android.device.examples.fragment.ConnectionInfoFragment.java
com.wit.android.device.examples.fragment.DeviceInfoFragment.java
com.wit.android.device.examples.fragment.FragmentsFactory.java
com.wit.android.device.examples.fragment.ScreenInfoFragment.java
com.wit.android.device.examples.fragment.ScreenInterfaceFragment.java
com.wit.android.device.examples.fragment.StorageFilesFragment.java
com.wit.android.device.examples.fragment.StorageInfoFragment.java
com.wit.android.device.examples.fragment.StorageInterfaceFragment.java
com.wit.android.device.examples.model.BatteryInfo.java
com.wit.android.device.examples.model.ConnectionInfo.java
com.wit.android.device.examples.model.SimpleInfo.java
com.wit.android.device.examples.model.StorageItem.java
com.wit.android.device.examples.module.StorageAssistant.java
com.wit.android.device.receiver.BatteryHealthReceiver.java
com.wit.android.device.receiver.BatteryPluggedStateReceiver.java
com.wit.android.device.receiver.BatteryStatusReceiver.java
com.wit.android.device.receiver.BroadcastProcessor.java
com.wit.android.device.receiver.ConnectionStateReceiver.java
com.wit.android.device.util.ConnectionUtils.java
com.wit.android.device.util.ScreenUtils.java
com.wit.android.device.util.StorageEditor.java
com.wit.android.device.util.StorageUtils.java