001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012: package org.tmatesoft.svn.core.internal.wc;
013:
014: import java.io.File;
015: import java.io.IOException;
016: import java.util.HashSet;
017: import java.util.Set;
018:
019: import org.tmatesoft.svn.core.SVNNodeKind;
020: import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil;
021: import org.tmatesoft.svn.util.SVNDebugLog;
022:
023: /**
024: * @version 1.1.1
025: * @author TMate Software Ltd.
026: */
027: public class SVNFileType {
028:
029: public static final SVNFileType UNKNOWN = new SVNFileType(0);
030: public static final SVNFileType NONE = new SVNFileType(1);
031: public static final SVNFileType FILE = new SVNFileType(2);
032: public static final SVNFileType SYMLINK = new SVNFileType(3);
033: public static final SVNFileType DIRECTORY = new SVNFileType(4);
034:
035: private static final boolean fastSymlinkResoution = !"false"
036: .equalsIgnoreCase(System
037: .getProperty(
038: "svnkit.fastSymlinkResolution",
039: System
040: .getProperty("javasvn.fastSymlinkResolution")));
041: private static final boolean canonPathCacheUsed = !"false"
042: .equalsIgnoreCase(System
043: .getProperty("sun.io.useCanonCaches"));
044: private static boolean detectSymlinks = !"false"
045: .equalsIgnoreCase(System.getProperty("svnkit.symlinks",
046: System.getProperty("javasvn.symlinks", "true")));
047:
048: private static final Set ADMIN_FILE_PARENTS = new HashSet();
049:
050: static {
051: ADMIN_FILE_PARENTS.add("text-base");
052: ADMIN_FILE_PARENTS.add("prop-base");
053: ADMIN_FILE_PARENTS.add("props");
054: ADMIN_FILE_PARENTS.add("wcprops");
055: ADMIN_FILE_PARENTS.add("tmp");
056: }
057:
058: private int myType;
059:
060: private SVNFileType(int type) {
061: myType = type;
062: }
063:
064: public String toString() {
065: switch (myType) {
066: case 0:
067: return "unknown";
068: case 1:
069: return "none";
070: case 2:
071: return "file";
072: case 3:
073: return "symlink";
074: case 4:
075: return "directory";
076: }
077: return Integer.toString(myType);
078: }
079:
080: public static void setSymlinkSupportEnabled(boolean enabled) {
081: detectSymlinks = enabled;
082: }
083:
084: public static boolean isSymlinkSupportEnabled() {
085: return detectSymlinks;
086: }
087:
088: public static SVNFileType getType(File file) {
089: if (file == null) {
090: return SVNFileType.UNKNOWN;
091: }
092: if (SVNFileUtil.isLinux || SVNFileUtil.isBSD
093: || SVNFileUtil.isOSX) {
094: if (detectSymlinks) {
095: SVNFileType ft = SVNJNAUtil.getFileType(file);
096: if (ft != null) {
097: return ft;
098: }
099: }
100: }
101: if (detectSymlinks && !SVNFileUtil.isWindows
102: && !isAdminFile(file)) {
103: if (canonPathCacheUsed && !fastSymlinkResoution
104: && SVNFileType.isSymlink(file)) {
105: return SVNFileType.SYMLINK;
106: } else if (!canonPathCacheUsed || fastSymlinkResoution) {
107: if (!file.exists()) {
108: File[] children = file.getParentFile() != null ? SVNFileListUtil
109: .listFiles(file.getParentFile())
110: : null;
111: for (int i = 0; children != null
112: && i < children.length; i++) {
113: File child = children[i];
114: if (child.getName().equals(file.getName())) {
115: if (SVNFileType.isSymlink(file)) {
116: return SVNFileType.SYMLINK;
117: }
118: }
119: }
120: } else {
121: String absolutePath = file.getAbsolutePath();
122: String canonicalPath;
123: try {
124: canonicalPath = file.getCanonicalPath();
125: } catch (IOException e) {
126: canonicalPath = file.getAbsolutePath();
127: }
128: if (!absolutePath.equals(canonicalPath)
129: && SVNFileType.isSymlink(file)) {
130: return SVNFileType.SYMLINK;
131: }
132: }
133: }
134: }
135:
136: if (file.isFile()) {
137: return SVNFileType.FILE;
138: } else if (file.isDirectory()) {
139: return SVNFileType.DIRECTORY;
140: } else if (!file.exists()) {
141: return SVNFileType.NONE;
142: }
143: return SVNFileType.UNKNOWN;
144: }
145:
146: public static boolean equals(SVNFileType type, SVNNodeKind nodeKind) {
147: if (nodeKind == SVNNodeKind.DIR) {
148: return type == SVNFileType.DIRECTORY;
149: } else if (nodeKind == SVNNodeKind.FILE) {
150: return type == SVNFileType.FILE
151: || type == SVNFileType.SYMLINK;
152: } else if (nodeKind == SVNNodeKind.NONE) {
153: return type == SVNFileType.NONE;
154: } else if (nodeKind == SVNNodeKind.UNKNOWN) {
155: return type == SVNFileType.UNKNOWN;
156: }
157: return false;
158: }
159:
160: private static boolean isAdminFile(File file) {
161: String path = file.getAbsolutePath().replace(
162: File.separatorChar, '/');
163: String adminDir = "/" + SVNFileUtil.getAdminDirectoryName();
164: return path.lastIndexOf(adminDir + "/") > 0
165: || path.endsWith(adminDir);
166: }
167:
168: private static boolean isSymlink(File file) {
169: String line = null;
170: try {
171: line = SVNFileUtil.execCommand(new String[] {
172: SVNFileUtil.LS_COMMAND, "-ld",
173: file.getAbsolutePath() });
174: } catch (Throwable th) {
175: SVNDebugLog.getDefaultLog().info(th);
176: }
177: return line != null && line.startsWith("l");
178: }
179:
180: public int getID() {
181: return myType;
182: }
183:
184: public boolean isFile() {
185: return this == SVNFileType.FILE || this == SVNFileType.SYMLINK;
186: }
187:
188: public static SVNNodeKind getNodeKind(SVNFileType type) {
189: if (type == null || type == SVNFileType.NONE
190: || type == SVNFileType.UNKNOWN) {
191: return SVNNodeKind.NONE;
192: } else if (type == SVNFileType.DIRECTORY) {
193: return SVNNodeKind.DIR;
194: }
195: return SVNNodeKind.FILE;
196: }
197:
198: }
|