/*
* Copyright 2014 Yaroslav Mytkalyk
* 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.docd.purefm.file;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.docd.purefm.Environment;
import com.docd.purefm.utils.MimeTypes;
import com.docd.purefm.utils.PFMFileUtils;
import com.docd.purefm.utils.StorageHelper;
public final class JavaFile implements GenericFile, Comparable<GenericFile> {
private static final long serialVersionUID = -2117911719748590982L;
@NonNull
private final File mFile;
@NonNull
private final Permissions p;
private final boolean isSymlink;
@Nullable
private final String mimeType;
public JavaFile(@NonNull final File file) {
this.mFile = file;
this.p = this.readPermissions();
this.isSymlink = this.detectSymlink();
this.mimeType = MimeTypes.getMimeType(file);
}
public JavaFile(@NonNull final File dir, @NonNull final String name) {
this.mFile = new File(dir, name);
this.p = this.readPermissions();
this.isSymlink = this.detectSymlink();
this.mimeType = MimeTypes.getMimeType(mFile);
}
public JavaFile(@NonNull final String dirPath, @NonNull final String name) {
this.mFile = new File(dirPath, name);
this.p = this.readPermissions();
this.isSymlink = this.detectSymlink();
this.mimeType = MimeTypes.getMimeType(mFile);
}
public JavaFile(@NonNull final String path) {
this.mFile = new File(path);
this.p = this.readPermissions();
this.isSymlink = this.detectSymlink();
this.mimeType = MimeTypes.getMimeType(mFile);
}
public JavaFile(@NonNull final URI uri) {
this.mFile = new File(uri);
this.p = this.readPermissions();
this.isSymlink = this.detectSymlink();
this.mimeType = MimeTypes.getMimeType(mFile);
}
/**
* {@inheritDoc}
*/
@NonNull
private Permissions readPermissions() {
boolean canWrite = mFile.canWrite();
if (canWrite) {
final StorageHelper.StorageVolume volume = Environment.volumeOfPath(
PFMFileUtils.fullPath(mFile));
if (volume != null) {
canWrite = !Environment.isReadOnly(volume);
}
}
return new Permissions(mFile.canRead(), canWrite, mFile.canExecute());
}
/**
* {@inheritDoc}
*/
@Nullable
private JavaFile[] convert(final File[] files) {
if (files == null) {
return null;
}
final JavaFile[] res = new JavaFile[files.length];
for (int i = 0; i < files.length; i++) {
res[i] = new JavaFile(files[i]);
}
return res;
}
private boolean detectSymlink() {
try {
return FileUtils.isSymlink(this.mFile);
} catch (IOException e) {
return false;
}
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public String getMimeType() {
return this.mimeType;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSymlink() {
return this.isSymlink;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isHidden() {
return this.mFile.isHidden();
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public File toFile() {
return this.mFile;
}
/**
* {@inheritDoc}
*/
@Override
public boolean delete() {
if (mFile.isDirectory()) {
try {
FileUtils.deleteDirectory(mFile);
return true;
} catch (IOException e) {
return false;
}
} else {
return this.mFile.delete();
}
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public JavaFile[] listFiles() {
return convert(this.mFile.listFiles());
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public JavaFile[] listFiles(final FileFilter filter) {
return convert(this.mFile.listFiles(filter));
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public JavaFile[] listFiles(final FilenameFilter filter) {
return convert(this.mFile.listFiles(filter));
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public JavaFile[] listFiles(final GenericFileFilter filter) {
final File[] files = this.mFile.listFiles();
if (files == null) {
return null;
}
final List<JavaFile> res = new LinkedList<>();
for (final File file : files) {
final JavaFile f = new JavaFile(file);
if (filter.accept(f)) {
res.add(f);
}
}
final JavaFile[] result = new JavaFile[res.size()];
int i = 0;
for (JavaFile f : res) {
result[i++] = f;
}
return result;
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public String[] list() {
return this.mFile.list();
}
/**
* {@inheritDoc}
*/
@Override
public long length() {
return this.mFile.length();
}
/**
* {@inheritDoc}
*/
@Override
public BigInteger lengthTotal() {
if (mFile.exists()) {
try {
return FileUtils.sizeOfAsBigInteger(mFile);
} catch (StackOverflowError e) {
//if we have too much directories, we can get this
return BigInteger.valueOf(-1);
}
}
return BigInteger.ZERO;
}
/**
* {@inheritDoc}
*/
@Override
public long lastModified() {
return this.mFile.lastModified();
}
/**
* {@inheritDoc}
*/
@Override
public boolean createNewFile() throws IOException {
return this.mFile.createNewFile();
}
/**
* {@inheritDoc}
*/
@Override
public boolean mkdir() {
return this.mFile.mkdir();
}
/**
* {@inheritDoc}
*/
@Override
public boolean mkdirs() {
return this.mFile.mkdirs();
}
/**
* Returns true, if this file points to the same location
* @param arg0 File to compare to
* @return true, if this file points to the same location
*/
@Override
public int compareTo(@NonNull final GenericFile arg0) {
return this.mFile.compareTo(arg0.toFile());
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public String getName() {
return this.mFile.getName();
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public String getPath() {
return this.mFile.getPath();
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public String getAbsolutePath() {
return this.mFile.getAbsolutePath();
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public String getCanonicalPath() throws IOException {
return this.mFile.getCanonicalPath();
}
@NonNull
@Override
public JavaFile getCanonicalFile() throws IOException {
return new JavaFile(this.mFile.getCanonicalPath());
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("SimplifiableIfStatement")
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof JavaFile) {
return ((JavaFile) obj).mFile.equals(this.mFile);
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public long getFreeSpace() {
return this.mFile.getFreeSpace();
}
/**
* {@inheritDoc}
*/
@Override
public long getTotalSpace() {
return this.mFile.getTotalSpace();
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public String getParent() {
return this.mFile.getParent();
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public JavaFile getParentFile() {
final File parent = this.mFile.getParentFile();
if (parent == null) {
return null;
}
return new JavaFile(parent);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isDirectory() {
return this.mFile.isDirectory();
}
/**
* {@inheritDoc}
*/
@Override
public boolean renameTo(@NonNull final GenericFile newName) {
return this.mFile.renameTo(newName.toFile());
}
/**
* {@inheritDoc}
*/
@NonNull
@Override
public Permissions getPermissions() {
return this.p;
}
/**
* {@inheritDoc}
*/
@Override
public boolean applyPermissions(final Permissions newPerm) {
boolean result;
result = mFile.setReadable(newPerm.ur);
result &= mFile.setWritable(newPerm.uw);
result &= mFile.setExecutable(newPerm.ux);
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean exists() {
return this.mFile.exists();
}
/**
* {@inheritDoc}
*/
@Override
public boolean canRead() {
return this.mFile.canRead();
}
/**
* {@inheritDoc}
*/
@Override
public boolean canWrite() {
return this.mFile.canWrite();
}
/**
* {@inheritDoc}
*/
@Override
public boolean canExecute() {
return this.mFile.canExecute();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return this.mFile.toString();
}
}