package com.apple.laf;
import java.io.*;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.Map.Entry;
import javax.swing.Icon;
import javax.swing.filechooser.FileView;
import com.apple.laf.AquaUtils.RecyclableSingleton;
class AquaFileView extends FileView {
private static final boolean DEBUG = false;
private static final int UNINITALIZED_LS_INFO = -1;
static final int kLSItemInfoIsPlainFile = 0x00000001;
static final int kLSItemInfoIsPackage = 0x00000002;
static final int kLSItemInfoIsApplication = 0x00000004;
static final int kLSItemInfoIsContainer = 0x00000008;
static final int kLSItemInfoIsAliasFile = 0x00000010;
static final int kLSItemInfoIsSymlink = 0x00000020;
static final int kLSItemInfoIsInvisible = 0x00000040;
static final int kLSItemInfoIsNativeApp = 0x00000080;
static final int kLSItemInfoIsClassicApp = 0x00000100;
static final int kLSItemInfoAppPrefersNative = 0x00000200;
static final int kLSItemInfoAppPrefersClassic = 0x00000400;
static final int kLSItemInfoAppIsScriptable = 0x00000800;
static final int kLSItemInfoIsVolume = 0x00001000;
static final int kLSItemInfoExtensionIsHidden = 0x00100000;
static {
java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("osxui"));
}
private static native String getNativePathToSharedJDKBundle();
private static native String getNativeMachineName();
private static native String getNativeDisplayName(final byte[] pathBytes, final boolean isDirectory);
private static native int getNativeLSInfo(final byte[] pathBytes, final boolean isDirectory);
private static native String getNativePathForResolvedAlias(final byte[] absolutePath, final boolean isDirectory);
static final RecyclableSingleton<String> machineName = new RecyclableSingleton<String>() {
@Override
protected String getInstance() {
return getNativeMachineName();
}
};
private static String getMachineName() {
return machineName.get();
}
protected static String getPathToRunningJDKBundle() {
return "";
}
protected static String getPathToSharedJDKBundle() {
return getNativePathToSharedJDKBundle();
}
static class FileInfo {
final boolean isDirectory;
final String absolutePath;
byte[] pathBytes;
String displayName;
Icon icon;
int launchServicesInfo = UNINITALIZED_LS_INFO;
FileInfo(final File file){
isDirectory = file.isDirectory();
absolutePath = file.getAbsolutePath();
try {
pathBytes = absolutePath.getBytes("UTF-8");
} catch (final UnsupportedEncodingException e) {
pathBytes = new byte[0];
}
}
}
final int MAX_CACHED_ENTRIES = 256;
protected final Map<File, FileInfo> cache = new LinkedHashMap<File, FileInfo>(){
protected boolean removeEldestEntry(final Entry<File, FileInfo> eldest) {
return size() > MAX_CACHED_ENTRIES;
}
};
FileInfo getFileInfoFor(final File file) {
final FileInfo info = cache.get(file);
if (info != null) return info;
final FileInfo newInfo = new FileInfo(file);
cache.put(file, newInfo);
return newInfo;
}
final AquaFileChooserUI fFileChooserUI;
public AquaFileView(final AquaFileChooserUI fileChooserUI) {
fFileChooserUI = fileChooserUI;
}
String _directoryDescriptionText() {
return fFileChooserUI.directoryDescriptionText;
}
String _fileDescriptionText() {
return fFileChooserUI.fileDescriptionText;
}
boolean _packageIsTraversable() {
return fFileChooserUI.fPackageIsTraversable == AquaFileChooserUI.kOpenAlways;
}
boolean _applicationIsTraversable() {
return fFileChooserUI.fApplicationIsTraversable == AquaFileChooserUI.kOpenAlways;
}
public String getName(final File f) {
final FileInfo info = getFileInfoFor(f);
if (info.displayName != null) return info.displayName;
final String nativeDisplayName = getNativeDisplayName(info.pathBytes, info.isDirectory);
if (nativeDisplayName != null) {
info.displayName = nativeDisplayName;
return nativeDisplayName;
}
final String displayName = f.getName();
if (f.isDirectory() && fFileChooserUI.getFileChooser().getFileSystemView().isRoot(f)) {
final String localMachineName = getMachineName();
info.displayName = localMachineName;
return localMachineName;
}
info.displayName = displayName;
return displayName;
}
public String getDescription(final File f) {
return f.getName();
}
public String getTypeDescription(final File f) {
if (f.isDirectory()) return _directoryDescriptionText();
return _fileDescriptionText();
}
public Icon getIcon(final File f) {
final FileInfo info = getFileInfoFor(f);
if (info.icon != null) return info.icon;
if (f == null) {
info.icon = AquaIcon.SystemIcon.getDocumentIconUIResource();
} else {
final AquaIcon.FileIcon fileIcon = new AquaIcon.FileIcon(f);
info.icon = fileIcon;
if (!fileIcon.hasIconRef()) {
if (f.isDirectory()) {
if (fFileChooserUI.getFileChooser().getFileSystemView().isRoot(f)) {
info.icon = AquaIcon.SystemIcon.getComputerIconUIResource();
} else if (f.getParent() == null || f.getParent().equals("/")) {
info.icon = AquaIcon.SystemIcon.getHardDriveIconUIResource();
} else {
info.icon = AquaIcon.SystemIcon.getFolderIconUIResource();
}
} else {
info.icon = AquaIcon.SystemIcon.getDocumentIconUIResource();
}
}
}
return info.icon;
}
public Boolean isTraversable(final File f) {
if (f.isDirectory()) {
if (_packageIsTraversable() && _applicationIsTraversable()) {
return Boolean.TRUE;
} else if (!_packageIsTraversable() && !_applicationIsTraversable()) {
if (isPackage(f) || isApplication(f)) return Boolean.FALSE;
} else if (!_applicationIsTraversable()) {
if (isApplication(f)) return Boolean.FALSE;
} else if (!_packageIsTraversable()) {
if (isPackage(f) && !isApplication(f)) return Boolean.FALSE;
}
return Boolean.TRUE;
}
if (isAlias(f)) {
final File realFile = resolveAlias(f);
return realFile.isDirectory() ? Boolean.TRUE : Boolean.FALSE;
}
return Boolean.FALSE;
}
int getLSInfoFor(final File f) {
final FileInfo info = getFileInfoFor(f);
if (info.launchServicesInfo == UNINITALIZED_LS_INFO) {
info.launchServicesInfo = getNativeLSInfo(info.pathBytes, info.isDirectory);
}
return info.launchServicesInfo;
}
boolean isAlias(final File f) {
final int lsInfo = getLSInfoFor(f);
return ((lsInfo & kLSItemInfoIsAliasFile) != 0) && ((lsInfo & kLSItemInfoIsSymlink) == 0);
}
boolean isApplication(final File f) {
return (getLSInfoFor(f) & kLSItemInfoIsApplication) != 0;
}
boolean isPackage(final File f) {
return (getLSInfoFor(f) & kLSItemInfoIsPackage) != 0;
}
File resolveAlias(final File mFile) {
if (mFile.exists() && !isAlias(mFile)) {
if (DEBUG) System.out.println("not an alias");
return mFile;
}
final LinkedList<String> components = getPathComponents(mFile);
if (components == null) {
if (DEBUG) System.out.println("getPathComponents is null ");
return mFile;
}
File file = new File("/");
for (final String nextComponent : components) {
file = new File(file, nextComponent);
final FileInfo info = getFileInfoFor(file);
if (!file.exists()) { return mFile; }
if (isAlias(file)) {
final String path = getNativePathForResolvedAlias(info.pathBytes, info.isDirectory);
if (path == null) return mFile;
file = new File(path);
}
}
return file;
}
private static LinkedList<String> getPathComponents(final File mFile) {
final LinkedList<String> componentList = new LinkedList<String>();
String parent;
File file = new File(mFile.getAbsolutePath());
componentList.add(0, file.getName());
while ((parent = file.getParent()) != null) {
file = new File(parent);
componentList.add(0, file.getName());
}
return componentList;
}
}