/*
* ====================================================================
* Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://svnkit.com/license.html
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
* ====================================================================
*/
package org.tmatesoft.svn.core.internal.wc;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.internal.util.SVNHashSet;
import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil;
import org.tmatesoft.svn.util.SVNDebugLog;
import org.tmatesoft.svn.util.SVNLogType;
/**
* @version 1.3
* @author TMate Software Ltd.
*/
public class SVNFileType {
public static final SVNFileType UNKNOWN = new SVNFileType(0);
public static final SVNFileType NONE = new SVNFileType(1);
public static final SVNFileType FILE = new SVNFileType(2);
public static final SVNFileType SYMLINK = new SVNFileType(3);
public static final SVNFileType DIRECTORY = new SVNFileType(4);
private static final boolean ourFastSymlinkResoution = !"false".equalsIgnoreCase(System.getProperty("svnkit.fastSymlinkResolution", System.getProperty("javasvn.fastSymlinkResolution")));
private static final boolean ourCanonPathCacheUsed = !"false".equalsIgnoreCase(System.getProperty("sun.io.useCanonCaches"));
private static boolean ourDetectSymlinks = !"false".equalsIgnoreCase(System.getProperty("svnkit.symlinks", System.getProperty("javasvn.symlinks", "true")));
private static final Set ADMIN_FILE_PARENTS = new SVNHashSet();
static {
ADMIN_FILE_PARENTS.add("text-base");
ADMIN_FILE_PARENTS.add("prop-base");
ADMIN_FILE_PARENTS.add("props");
ADMIN_FILE_PARENTS.add("wcprops");
ADMIN_FILE_PARENTS.add("tmp");
}
private int myType;
private SVNFileType(int type) {
myType = type;
}
public String toString() {
switch(myType) {
case 0: return "unknown";
case 1: return "none";
case 2: return "file";
case 3: return "symlink";
case 4: return "directory";
}
return Integer.toString(myType);
}
public static synchronized void setSymlinkSupportEnabled(boolean enabled) {
ourDetectSymlinks = enabled;
}
public static synchronized boolean isSymlinkSupportEnabled() {
return ourDetectSymlinks;
}
public static SVNFileType getType(File file) {
final boolean detectSymlinks = isSymlinkSupportEnabled();
if (file == null) {
return SVNFileType.UNKNOWN;
}
if (SVNFileUtil.isLinux || SVNFileUtil.isBSD || SVNFileUtil.isOSX || SVNFileUtil.isSolaris) {
if (detectSymlinks) {
SVNFileType ft = SVNJNAUtil.getFileType(file);
if (ft != null) {
return ft;
}
}
}
if (detectSymlinks && SVNFileUtil.symlinksSupported() && !isAdminFile(file)) {
if (ourCanonPathCacheUsed && !ourFastSymlinkResoution && SVNFileType.isSymlink(file)) {
return SVNFileType.SYMLINK;
} else if (!ourCanonPathCacheUsed || ourFastSymlinkResoution) {
if (!file.exists()) {
File[] children = file.getParentFile() != null ? SVNFileListUtil.listFiles(file.getParentFile()) : null;
for (int i = 0; children != null && i < children.length; i++) {
File child = children[i];
if (child.getName().equals(file.getName())) {
if (SVNFileType.isSymlink(file)) {
return SVNFileType.SYMLINK;
}
}
}
} else {
String absolutePath = file.getAbsolutePath();
String canonicalPath;
try {
canonicalPath = file.getCanonicalPath();
} catch (IOException e) {
canonicalPath = file.getAbsolutePath();
}
if (!absolutePath.equals(canonicalPath) && SVNFileType.isSymlink(file)) {
return SVNFileType.SYMLINK;
}
}
}
}
if (file.isFile()) {
return SVNFileType.FILE;
} else if (file.isDirectory()) {
return SVNFileType.DIRECTORY;
} else if (!file.exists()) {
return SVNFileType.NONE;
}
return SVNFileType.UNKNOWN;
}
public static boolean equals(SVNFileType type, SVNNodeKind nodeKind) {
if (nodeKind == SVNNodeKind.DIR) {
return type == SVNFileType.DIRECTORY;
} else if (nodeKind == SVNNodeKind.FILE) {
return type == SVNFileType.FILE || type == SVNFileType.SYMLINK;
} else if (nodeKind == SVNNodeKind.NONE) {
return type == SVNFileType.NONE;
} else if (nodeKind == SVNNodeKind.UNKNOWN) {
return type == SVNFileType.UNKNOWN;
}
return false;
}
private static boolean isAdminFile(File file) {
String path = file.getAbsolutePath().replace(File.separatorChar, '/');
String adminDir = "/" + SVNFileUtil.getAdminDirectoryName();
return path.lastIndexOf(adminDir + "/") > 0 || path.endsWith(adminDir);
}
private static boolean isSymlink(File file) {
String line = null;
try {
line = SVNFileUtil.execCommand(new String[] {
SVNFileUtil.LS_COMMAND, "-ld", file.getAbsolutePath()
});
} catch (Throwable th) {
SVNDebugLog.getDefaultLog().logFine(SVNLogType.DEFAULT, th);
}
return line != null && line.startsWith("l");
}
public int getID() {
return myType;
}
public boolean isFile() {
return this == SVNFileType.FILE || this == SVNFileType.SYMLINK;
}
public static SVNNodeKind getNodeKind(SVNFileType type) {
if (type == null || type == SVNFileType.NONE || type == SVNFileType.UNKNOWN) {
return SVNNodeKind.NONE;
} else if (type == SVNFileType.DIRECTORY) {
return SVNNodeKind.DIR;
}
return SVNNodeKind.FILE;
}
}