Merge remote-tracking branch 'origin/master'

This commit is contained in:
Kirill Likhodedov
2012-03-15 20:52:11 +04:00
14 changed files with 460 additions and 181 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.openapi.vfs.impl.jar;
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
@@ -224,4 +225,12 @@ public class JarHandlerBase {
return getEntryInfo(fileOrDirectory) != null;
}
@Nullable
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
synchronized (lock) {
final ZipEntry entry = convertToEntry(file);
return entry != null ? new FileAttributes(entry.isDirectory(), false, false, entry.getSize(), entry.getTime(), false) : null;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,9 +113,10 @@ public class JdkUtil {
return null;
}
public static boolean checkForJdk(File file) {
file = new File(file.getAbsolutePath() + File.separator + "bin");
if (!file.exists()) return false;
public static boolean checkForJdk(final File homePath) {
File binPath = new File(homePath.getAbsolutePath() + File.separator + "bin");
if (!binPath.exists()) return false;
FileFilter fileFilter = new FileFilter() {
@SuppressWarnings({"HardCodedStringLiteral"})
public boolean accept(File f) {
@@ -124,21 +125,34 @@ public class JdkUtil {
Comparing.strEqual(FileUtil.getNameWithoutExtension(f), "javah");
}
};
File[] children = file.listFiles(fileFilter);
return children != null && children.length >= 2;
File[] children = binPath.listFiles(fileFilter);
return children != null && children.length >= 2 &&
checkForRuntime(homePath.getAbsolutePath());
}
public static boolean checkForJre(String file) {
File ioFile = new File(new File(file.replace('/', File.separatorChar)).getAbsolutePath() + File.separator + "bin");
if (!ioFile.exists()) return false;
public static boolean checkForJre(String homePath) {
homePath = new File(FileUtil.toSystemDependentName(homePath)).getAbsolutePath();
File binPath = new File(homePath + File.separator + "bin");
if (!binPath.exists()) return false;
FileFilter fileFilter = new FileFilter() {
@SuppressWarnings({"HardCodedStringLiteral"})
public boolean accept(File f) {
return !f.isDirectory() && Comparing.strEqual(FileUtil.getNameWithoutExtension(f), "java");
}
};
File[] children = ioFile.listFiles(fileFilter);
return children != null && children.length >= 1;
File[] children = binPath.listFiles(fileFilter);
return children != null && children.length >= 1 &&
checkForRuntime(homePath);
}
public static boolean checkForRuntime(final String homePath) {
return new File(homePath + File.separator + "jre" + File.separator + "lib" + File.separator + "rt.jar").exists() ||
new File(homePath + File.separator + "lib" + File.separator + "rt.jar").exists() ||
new File(homePath + File.separator + ".." + File.separator + "Classes" + File.separator + "classes.jar").exists() ||
new File(homePath + File.separator + "jre" + File.separator + "lib" + File.separator + "vm.jar").exists();
}
public static GeneralCommandLine setupJVMCommandLine(final String exePath,
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.openapi.vfs.newvfs;
import com.intellij.openapi.application.ApplicationManager;
@@ -31,9 +27,13 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author max
*/
public abstract class NewVirtualFile extends VirtualFile implements VirtualFileWithId {
private volatile long myModificationStamp = LocalTimeCounter.currentTime();
private final AtomicLong myModificationStamp = new AtomicLong(LocalTimeCounter.currentTime());
public boolean isValid() {
ApplicationManager.getApplication().assertReadAccessAllowed();
@@ -50,6 +50,9 @@ public abstract class NewVirtualFile extends VirtualFile implements VirtualFileW
public abstract NewVirtualFile getParent();
@Nullable
public abstract NewVirtualFile getCanonicalFile();
@Nullable
public abstract NewVirtualFile findChild(@NotNull @NonNls final String name);
@@ -75,11 +78,11 @@ public abstract class NewVirtualFile extends VirtualFile implements VirtualFileW
}
public long getModificationStamp() {
return myModificationStamp;
return myModificationStamp.get();
}
public void setModificationStamp(long modificationStamp) {
myModificationStamp = modificationStamp;
myModificationStamp.set(modificationStamp);
}
public abstract void setWritable(boolean writable) throws IOException;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,11 +14,9 @@
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.openapi.vfs.newvfs;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileListener;
@@ -32,6 +30,9 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author max
*/
public abstract class NewVirtualFileSystem extends VirtualFileSystem implements FileSystemInterface, CachingVirtualFileSystem {
private final Map<VirtualFileListener, VirtualFileListener> myListenerWrappers = new HashMap<VirtualFileListener, VirtualFileListener>();
@@ -150,4 +151,14 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements
*/
@FileUtil.FileBooleanAttributes
public abstract int getBooleanAttributes(@NotNull final VirtualFile file, @FileUtil.FileBooleanAttributes int flags);
/**
* Reads various file attributes in one shot (to reduce the number of native I/O calls).
*
* @param file file to get attributes of.
* @return attributes of a given file, or <code>null</code> if the file doesn't exist.
* @since 11.1
*/
@Nullable
public abstract FileAttributes getAttributes(@NotNull VirtualFile file);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,11 @@
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.openapi.vfs.ex.temp;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -40,6 +38,9 @@ import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author max
*/
public class TempFileSystem extends NewVirtualFileSystem {
private final FSItem myRoot = new FSDir(null, "/");
@@ -375,4 +376,12 @@ public class TempFileSystem extends NewVirtualFileSystem {
int regular = isDir == 0 ? FileUtil.BA_REGULAR : 0;
return isDir | exists | regular;
}
@Override
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
final FSItem item = convert(file);
if (item == null) return null;
final long length = item instanceof FSFile ? ((FSFile)item).myContent.length : 0;
return new FileAttributes(item.isDirectory(), false, false, length, item.myTimestamp, item.myWritable);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
@@ -381,4 +382,19 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
}
return exists | isDir | regular;
}
@Override
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
final JarHandler handler = getHandler(file);
if (handler == null) return null;
if (file.getParent() == null) {
final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
final VirtualFile originalFile = localFileSystem.findFileByIoFile(handler.getOriginalFile());
assert originalFile != null : file;
return localFileSystem.getAttributes(originalFile);
}
return handler.getAttributes(file);
}
}
@@ -22,6 +22,8 @@ import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -45,17 +47,14 @@ import java.io.IOException;
import java.util.*;
public final class LocalFileSystemImpl extends LocalFileSystemBase implements ApplicationComponent {
private final JBReentrantReadWriteLock LOCK = LockFactory.createReadWriteLock();
final JBLock WRITE_LOCK = LOCK.writeLock();
private final JBLock WRITE_LOCK = LOCK.writeLock();
private final List<WatchRequestImpl> myRootsToWatch = new ArrayList<WatchRequestImpl>();
private WatchRequest[] myCachedNormalizedRequests = null;
private final FileWatcher myWatcher;
private final LocalFileSystemBase myNativeFileSystem;
private static class WatchRequestImpl implements WatchRequest {
public final String myRootPath;
@@ -132,7 +131,6 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
if (myWatcher.isOperational()) {
new StoreRefreshStatusThread().start();
}
myNativeFileSystem = null;
}
@Override
@@ -471,12 +469,6 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
return false;
}
@NonNls
public String toString() {
return "LocalFileSystem";
}
@Override
public void refreshWithoutFileWatcher(final boolean asynchronous) {
Runnable heavyRefresh = new Runnable() {
@@ -499,33 +491,12 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
}
@Override
public boolean exists(@NotNull final VirtualFile fileOrDirectory) {
if (myNativeFileSystem == null) return super.exists(fileOrDirectory);
else return myNativeFileSystem.exists(fileOrDirectory);
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(file.getPath()));
}
@Override
public long getTimeStamp(@NotNull final VirtualFile file) {
if (myNativeFileSystem == null) return super.getTimeStamp(file);
else return myNativeFileSystem.getTimeStamp(file);
}
@Override
public boolean isDirectory(@NotNull final VirtualFile file) {
if (myNativeFileSystem == null) return super.isDirectory(file);
else return myNativeFileSystem.isDirectory(file);
}
@Override
public boolean isWritable(@NotNull final VirtualFile file) {
if (myNativeFileSystem == null) return super.isWritable(file);
else return myNativeFileSystem.isWritable(file);
}
@Override
@NotNull
public String[] list(@NotNull final VirtualFile file) {
if (myNativeFileSystem == null) return super.list(file);
else return myNativeFileSystem.list(file);
@NonNls
public String toString() {
return "LocalFileSystem";
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -97,7 +97,7 @@ public class Win32Kernel {
}
@Nullable
private FileInfo doGetInfo(String path) {
FileInfo doGetInfo(String path) {
FileInfo info = myCache.get(path);
if (info == null) {
info = myKernel.getInfo(path.replace('/', '\\'));
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@ package com.intellij.openapi.vfs.impl.win32;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.local.LocalFileSystemBase;
import com.intellij.util.ArrayUtil;
@@ -202,4 +204,20 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
return myKernel.getBooleanAttributes(file.getPath(), flags);
}
@Override
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
final FileInfo fileInfo = myKernel.doGetInfo(FileUtil.toSystemDependentName(file.getPath()));
if (fileInfo == null) return null;
final boolean isDirectory = isSet(fileInfo, Win32Kernel.FILE_ATTRIBUTE_DIRECTORY);
final boolean isSymlink = isSet(fileInfo, Win32Kernel.FILE_ATTRIBUTE_REPARSE_POINT);
final boolean isSpecial = isSet(fileInfo, Win32Kernel.FILE_ATTRIBUTE_DEVICE);
final boolean isWritable = !isSet(fileInfo, Win32Kernel.FILE_ATTRIBUTE_READONLY);
return new FileAttributes(isDirectory, isSymlink, isSpecial, fileInfo.length, fileInfo.timestamp, isWritable);
}
private static boolean isSet(final FileInfo fileInfo, final int bit) {
return (fileInfo.attributes & bit) == bit;
}
}
@@ -499,10 +499,10 @@ public abstract class VirtualFileSystemEntry extends NewVirtualFile {
}
@Override
public VirtualFile getCanonicalFile() {
public NewVirtualFile getCanonicalFile() {
if (getFlagInt(HAS_SYMLINK_FLAG)) {
final String path = getCanonicalPath();
return path != null ? getFileSystem().findFileByPath(path) : null;
return path != null ? (NewVirtualFile)getFileSystem().findFileByPath(path) : null;
}
return this;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.mock;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileOperationsHandler;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -256,4 +257,9 @@ public class MockLocalFileSystem extends LocalFileSystem {
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
return 0;
}
@Override
public FileAttributes getAttributes(@NotNull VirtualFile file) {
return null;
}
}
@@ -0,0 +1,138 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* 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.intellij.openapi.util.io;
import com.intellij.util.StringBuilderSpinAllocator;
import org.intellij.lang.annotations.MagicConstant;
/**
* @version 11.1
* @see FileSystemUtil#getAttributes(String)
*/
@SuppressWarnings("OctalInteger")
public final class FileAttributes {
public static final int OWNER_READ = 0400;
public static final int OWNER_WRITE = 0200;
public static final int OWNER_EXECUTE = 0100;
public static final int GROUP_READ = 0040;
public static final int GROUP_WRITE = 0020;
public static final int GROUP_EXECUTE = 0010;
public static final int OTHERS_READ = 0004;
public static final int OTHERS_WRITE = 0002;
public static final int OTHERS_EXECUTE = 0001;
@MagicConstant(flags = {
OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE
})
public @interface Permissions { }
public final boolean isFile;
public final boolean isDirectory;
public final boolean isSymlink;
public final boolean isSpecial;
/** In bytes, 0 for symlinks and special files. */
public final long length;
/** In milliseconds (note that actual resolution may be less accurate). */
public final long lastModified;
/** UNIX permission bits (for Windows only OWNER_WRITE matters and OWNER_READ/EXECUTE are always set), or -1 if not supported. */
@Permissions
public final int permissions;
// todo: hidden flag (?)
public FileAttributes(final boolean isDirectory,
final boolean isSymlink,
final boolean isSpecial,
final long length,
final long lastModified,
final boolean writable) {
this(isDirectory, isSymlink, isSpecial, length, lastModified, OWNER_READ | OWNER_EXECUTE | (writable ? OWNER_WRITE : 0));
}
public FileAttributes(final boolean isDirectory,
final boolean isSymlink,
final boolean isSpecial,
final long length,
final long lastModified,
@Permissions final int permissions) {
this.isFile = !isDirectory && !isSymlink && !isSpecial;
this.isDirectory = isDirectory;
this.isSymlink = isSymlink;
this.isSpecial = isSpecial;
this.length = isSymlink || isSpecial ? 0 : length;
this.lastModified = lastModified;
this.permissions = permissions;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final FileAttributes that = (FileAttributes)o;
if (isDirectory != that.isDirectory) return false;
if (isFile != that.isFile) return false;
if (isSpecial != that.isSpecial) return false;
if (isSymlink != that.isSymlink) return false;
if (lastModified != that.lastModified) return false;
if (permissions != that.permissions) return false;
if (length != that.length) return false;
return true;
}
@Override
public int hashCode() {
int result = (isFile ? 1 : 0);
result = 31 * result + (isDirectory ? 1 : 0);
result = 31 * result + (isSymlink ? 1 : 0);
result = 31 * result + (isSpecial ? 1 : 0);
result = 31 * result + (int)(length ^ (length >>> 32));
result = 31 * result + (int)(lastModified ^ (lastModified >>> 32));
result = 31 * result + permissions;
return result;
}
@Override
public String toString() {
final StringBuilder sb = StringBuilderSpinAllocator.alloc();
try {
sb.append("[type:");
if (isFile) sb.append('f');
if (isDirectory) sb.append('d');
if (isSymlink) sb.append('l');
if (isSpecial) sb.append('!');
sb.append(" length:").append(length);
sb.append(" modified:").append(lastModified);
if (permissions != -1) {
sb.append(" mode:").append(Integer.toOctalString(permissions));
}
sb.append(']');
return sb.toString();
}
finally {
StringBuilderSpinAllocator.dispose(sb);
}
}
}
@@ -27,61 +27,69 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
// todo[r.sh] read attributes in one shot (IDEA 12)
// todo[r.sh] use NIO2 API after migration to JDK 7
/**
* @version 11.1
*/
public class FileSystemUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileSystemUtil");
@Nullable
@NotNull
private static final Mediator ourMediator;
static {
Mediator mediator = null;
if (SystemInfo.areSymLinksSupported) {
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
try {
mediator = new Jdk7MediatorImpl();
mediator.isSymLink("/"); // quick test
}
catch (Throwable t) {
if ("1.7.0-ea".equals(SystemInfo.JAVA_VERSION)) {
LOG.warn(t);
}
else {
LOG.error(t);
}
mediator = null;
}
// todo: move IdeaWin32 interface to this package, add mediator
if (SystemInfo.isLinux || SystemInfo.isMac || SystemInfo.isSolaris || SystemInfo.isFreeBSD) {
try {
mediator = new JnaUnixMediatorImpl();
mediator.getAttributes("/"); // quick test
}
if (mediator == null) {
if (SystemInfo.isLinux || SystemInfo.isMac || SystemInfo.isSolaris || SystemInfo.isFreeBSD) {
try {
mediator = new JnaUnixMediatorImpl();
mediator.isSymLink("/"); // quick test
}
catch (Throwable t) {
LOG.error(t);
mediator = null;
}
}
catch (Throwable t) {
LOG.error(t);
mediator = null;
}
}
if (mediator == null && SystemInfo.isJavaVersionAtLeast("1.7") && !"1.7.0-ea".equals(SystemInfo.JAVA_VERSION)) {
try {
mediator = new Jdk7MediatorImpl();
mediator.getAttributes("/"); // quick test
}
catch (Throwable t) {
LOG.error(t);
mediator = null;
}
}
if (mediator == null) {
// todo: after introducing IdeaWin32 mediator, fail tests at this point, or issue a warning in production
mediator = new StandardMediatorImpl();
}
ourMediator = mediator;
}
private FileSystemUtil() { }
public static boolean isSymLink(@NotNull final String path) {
@Nullable
public static FileAttributes getAttributes(@NotNull final String path) {
try {
return ourMediator != null && ourMediator.isSymLink(path);
return ourMediator.getAttributes(path);
}
catch (Exception e) {
LOG.warn(e);
return false;
}
return null;
}
public static boolean isSymLink(@NotNull final String path) {
final FileAttributes attributes = getAttributes(path);
return attributes != null && attributes.isSymlink;
}
public static boolean isSymLink(@NotNull final File file) {
@@ -90,17 +98,15 @@ public class FileSystemUtil {
@Nullable
public static String resolveSymLink(@NotNull final String path) {
if (ourMediator != null) {
try {
final String realPath = ourMediator.resolveSymLink(path);
if (realPath != null && new File(realPath).exists()) {
return realPath;
}
}
catch (Exception e) {
LOG.warn(e);
try {
final String realPath = ourMediator.resolveSymLink(path);
if (realPath != null && new File(realPath).exists()) {
return realPath;
}
}
catch (Exception e) {
LOG.warn(e);
}
return null;
}
@@ -110,15 +116,8 @@ public class FileSystemUtil {
}
public static int getPermissions(@NotNull final String path) {
if (SystemInfo.isUnix && ourMediator != null) {
try {
return ourMediator.getPermissions(path);
}
catch (Exception e) {
LOG.warn(e);
}
}
return -1;
final FileAttributes attributes = getAttributes(path);
return attributes != null ? attributes.permissions : -1;
}
public static int getPermissions(@NotNull final File file) {
@@ -126,7 +125,7 @@ public class FileSystemUtil {
}
public static void setPermissions(@NotNull final String path, final int permissions) {
if (SystemInfo.isUnix && ourMediator != null) {
if (SystemInfo.isUnix) {
try {
ourMediator.setPermissions(path, permissions);
}
@@ -141,16 +140,16 @@ public class FileSystemUtil {
}
private interface Mediator {
boolean isSymLink(@NotNull String path) throws Exception;
@Nullable
FileAttributes getAttributes(@NotNull String path) throws Exception;
@Nullable
String resolveSymLink(@NotNull String path) throws Exception;
int getPermissions(@NotNull String path) throws Exception;
void setPermissions(@NotNull String path, int permissions) throws Exception;
}
// todo[r.sh] remove reflection after migration to JDK 7
@SuppressWarnings("OctalInteger")
private static class Jdk7MediatorImpl implements Mediator {
private final Object myDefaultFileSystem;
@@ -158,8 +157,9 @@ public class FileSystemUtil {
private final Method myIsSymbolicLink;
private final Object myLinkOptions;
private final Object myNoFollowLinkOptions;
private final Method myGetAttribute;
private final Method myReadAttributes;
private final Method mySetAttribute;
private final Method myToMillis;
private Jdk7MediatorImpl() throws Exception {
myDefaultFileSystem = Class.forName("java.nio.file.FileSystems").getMethod("getDefault").invoke(null);
@@ -168,7 +168,8 @@ public class FileSystemUtil {
myGetPath.setAccessible(true);
final Class<?> pathClass = Class.forName("java.nio.file.Path");
myIsSymbolicLink = Class.forName("java.nio.file.Files").getMethod("isSymbolicLink", pathClass);
final Class<?> filesClass = Class.forName("java.nio.file.Files");
myIsSymbolicLink = filesClass.getMethod("isSymbolicLink", pathClass);
myIsSymbolicLink.setAccessible(true);
final Class<?> linkOptClass = Class.forName("java.nio.file.LinkOption");
@@ -177,14 +178,35 @@ public class FileSystemUtil {
Array.set(myNoFollowLinkOptions, 0, linkOptClass.getField("NOFOLLOW_LINKS").get(null));
final Class<?> linkOptArrClass = myLinkOptions.getClass();
myGetAttribute = Class.forName("java.nio.file.Files").getMethod("getAttribute", pathClass, String.class, linkOptArrClass);
mySetAttribute = Class.forName("java.nio.file.Files").getMethod("setAttribute", pathClass, String.class, Object.class, linkOptArrClass);
myReadAttributes = filesClass.getMethod("readAttributes", pathClass, String.class, linkOptArrClass);
myReadAttributes.setAccessible(true);
mySetAttribute = filesClass.getMethod("setAttribute", pathClass, String.class, Object.class, linkOptArrClass);
mySetAttribute.setAccessible(true);
final Class<?> fileTimeClass = Class.forName("java.nio.file.attribute.FileTime");
myToMillis = fileTimeClass.getMethod("toMillis");
myToMillis.setAccessible(true);
}
@Override
public boolean isSymLink(@NotNull final String path) throws Exception {
public FileAttributes getAttributes(@NotNull final String path) throws Exception {
final Object pathObj = myGetPath.invoke(myDefaultFileSystem, path, ArrayUtil.EMPTY_STRING_ARRAY);
return (Boolean)myIsSymbolicLink.invoke(null, pathObj);
try {
final Map attributes = (Map)myReadAttributes.invoke(null, pathObj, "posix:permissions,*", myNoFollowLinkOptions);
return new FileAttributes((Boolean)attributes.get("isDirectory"),
(Boolean)attributes.get("isSymbolicLink"),
(Boolean)attributes.get("isOther"),
(Long)attributes.get("size"),
(Long)myToMillis.invoke(attributes.get("lastModifiedTime")),
decodePermissions(attributes.get("permissions")));
}
catch (InvocationTargetException e) {
final Throwable cause = e.getCause();
if (cause != null && "java.nio.file.NoSuchFileException".equals(cause.getClass().getName())) {
return null;
}
throw e;
}
}
@Override
@@ -196,38 +218,30 @@ public class FileSystemUtil {
return toRealPath.invoke(pathObj, myLinkOptions).toString();
}
@Override
public int getPermissions(@NotNull final String path) throws Exception {
final Object pathObj = myGetPath.invoke(myDefaultFileSystem, path, ArrayUtil.EMPTY_STRING_ARRAY);
final Object attribute = myGetAttribute.invoke(null, pathObj, POSIX_PERMISSIONS_ATTR, myNoFollowLinkOptions);
return decodePermissions(attribute);
}
@Override
public void setPermissions(@NotNull final String path, final int permissions) throws Exception {
final Object pathObj = myGetPath.invoke(myDefaultFileSystem, path, ArrayUtil.EMPTY_STRING_ARRAY);
final Object attribute = encodePermissions(permissions);
if (attribute != null) {
mySetAttribute.invoke(null, pathObj, POSIX_PERMISSIONS_ATTR, attribute, myLinkOptions);
mySetAttribute.invoke(null, pathObj, "posix:permissions", attribute, myLinkOptions);
}
}
private static final String POSIX_PERMISSIONS_ATTR = "posix:permissions";
private static final Map<String, Integer> ATTRIBUTES_MAP;
static {
ATTRIBUTES_MAP = new HashMap<String, Integer>();
ATTRIBUTES_MAP.put("OWNER_READ", 0400);
ATTRIBUTES_MAP.put("OWNER_WRITE", 0200);
ATTRIBUTES_MAP.put("OWNER_EXECUTE", 0100);
ATTRIBUTES_MAP.put("GROUP_READ", 0040);
ATTRIBUTES_MAP.put("GROUP_WRITE", 0020);
ATTRIBUTES_MAP.put("GROUP_EXECUTE", 0010);
ATTRIBUTES_MAP.put("OTHERS_READ", 0004);
ATTRIBUTES_MAP.put("OTHERS_WRITE", 0002);
ATTRIBUTES_MAP.put("OTHERS_EXECUTE", 0001);
ATTRIBUTES_MAP.put("OWNER_READ", FileAttributes.OWNER_READ);
ATTRIBUTES_MAP.put("OWNER_WRITE", FileAttributes.OWNER_WRITE);
ATTRIBUTES_MAP.put("OWNER_EXECUTE", FileAttributes.OWNER_EXECUTE);
ATTRIBUTES_MAP.put("GROUP_READ", FileAttributes.GROUP_READ);
ATTRIBUTES_MAP.put("GROUP_WRITE", FileAttributes.GROUP_WRITE);
ATTRIBUTES_MAP.put("GROUP_EXECUTE", FileAttributes.GROUP_EXECUTE);
ATTRIBUTES_MAP.put("OTHERS_READ", FileAttributes.OTHERS_READ);
ATTRIBUTES_MAP.put("OTHERS_WRITE", FileAttributes.OTHERS_WRITE);
ATTRIBUTES_MAP.put("OTHERS_EXECUTE", FileAttributes.OTHERS_EXECUTE);
}
@FileAttributes.Permissions
private static int decodePermissions(final Object o) {
if (!(o instanceof Collection)) return -1;
@@ -236,6 +250,7 @@ public class FileSystemUtil {
final Integer bit = ATTRIBUTES_MAP.get(attr.toString());
if (bit != null) value |= bit;
}
//noinspection MagicConstant
return value;
}
@@ -260,11 +275,14 @@ public class FileSystemUtil {
}
// thanks to SVNKit for the idea
@SuppressWarnings("OctalInteger")
private static class JnaUnixMediatorImpl implements Mediator {
@SuppressWarnings("OctalInteger")
private interface LibC extends Library {
// from stat(2)
int S_MASK = 0177777;
int S_IFLNK = 0120000;
int S_IFLNK = 0120000; // symbolic link
int S_IFREG = 0100000; // regular file
int S_IFDIR = 0040000; // directory
int PERM_MASK = 0777;
int lstat(String path, Pointer stat);
@@ -274,34 +292,45 @@ public class FileSystemUtil {
private final LibC myLibC;
private final Memory mySharedMem;
private final int myOffset;
private final int myModeOffset;
private final int mySizeOffset;
private final int myTimeOffset;
private JnaUnixMediatorImpl() throws Exception {
myLibC = (LibC)Native.loadLibrary("c", LibC.class);
mySharedMem = new Memory(512);
myOffset = SystemInfo.isLinux ? (SystemInfo.is32Bit ? 16 : 24) :
SystemInfo.isMac | SystemInfo.isFreeBSD ? 8 :
SystemInfo.isSolaris ? (SystemInfo.is32Bit ? 20 : 16) :
-1;
if (myOffset < 0) throw new IllegalStateException("Unsupported OS: " + SystemInfo.OS_NAME);
}
private synchronized int getMode(final String path) {
mySharedMem.clear();
final int res = SystemInfo.isLinux ? myLibC.__lxstat64(0, path, mySharedMem) : myLibC.lstat(path, mySharedMem);
if (res == 0) {
return (SystemInfo.isLinux ? mySharedMem.getInt(myOffset) : mySharedMem.getShort(myOffset)) & LibC.S_MASK;
}
else {
LOG.debug("lstat(" + path + "): " + res);
return -1;
}
myModeOffset = SystemInfo.isLinux ? (SystemInfo.is32Bit ? 16 : 24) :
SystemInfo.isMac | SystemInfo.isFreeBSD ? 8 :
SystemInfo.isSolaris ? (SystemInfo.is32Bit ? 20 : 16) :
-1;
mySizeOffset = SystemInfo.isLinux ? (SystemInfo.is32Bit ? 44 : 48) :
SystemInfo.isMac | SystemInfo.isFreeBSD ? (SystemInfo.is32Bit ? 48 : 72) :
SystemInfo.isSolaris ? (SystemInfo.is32Bit ? 48 : 40) :
-1;
myTimeOffset = SystemInfo.isLinux ? (SystemInfo.is32Bit ? 72 : 88) :
SystemInfo.isMac | SystemInfo.isFreeBSD ? 40 :
SystemInfo.isSolaris ? 64 :
-1;
if (myModeOffset < 0) throw new IllegalStateException("Unsupported OS: " + SystemInfo.OS_NAME);
}
@Override
public boolean isSymLink(@NotNull final String path) throws Exception {
final int mode = getMode(path);
return mode != -1 && (mode & LibC.S_IFLNK) == LibC.S_IFLNK;
public synchronized FileAttributes getAttributes(@NotNull final String path) throws Exception {
mySharedMem.clear();
final int res = SystemInfo.isLinux ? myLibC.__lxstat64(0, path, mySharedMem) : myLibC.lstat(path, mySharedMem);
if (res == 0) {
final int mode = (SystemInfo.isLinux ? mySharedMem.getInt(myModeOffset) : mySharedMem.getShort(myModeOffset)) & LibC.S_MASK;
final boolean isDirectory = (mode & LibC.S_IFDIR) == LibC.S_IFDIR;
final boolean isSymlink = (mode & LibC.S_IFLNK) == LibC.S_IFLNK;
final boolean isSpecial = !isDirectory && !isSymlink && (mode & LibC.S_IFREG) == 0;
final long size = mySharedMem.getLong(mySizeOffset);
final long mTime1 = SystemInfo.is32Bit ? mySharedMem.getInt(myTimeOffset) : mySharedMem.getLong(myTimeOffset);
final long mTime2 = SystemInfo.is32Bit ? mySharedMem.getInt(myTimeOffset + 4) : mySharedMem.getLong(myTimeOffset + 8);
final long mTime = mTime1 * 1000 + mTime2 / 1000000;
@FileAttributes.Permissions final int permissions = mode & LibC.PERM_MASK;
return new FileAttributes(isDirectory, isSymlink, isSpecial, size, mTime, permissions);
}
return null;
}
@Override
@@ -309,15 +338,68 @@ public class FileSystemUtil {
return new File(path).getCanonicalPath();
}
@Override
public int getPermissions(@NotNull final String path) throws Exception {
final int mode = getMode(path);
return mode != -1 ? mode & LibC.PERM_MASK : -1;
}
@Override
public void setPermissions(@NotNull final String path, final int permissions) throws Exception {
myLibC.chmod(path, permissions & LibC.PERM_MASK);
}
}
private static class StandardMediatorImpl implements Mediator {
// from java.io.FileSystem
private static final int BA_REGULAR = 0x02;
private static final int BA_DIRECTORY = 0x04;
private final Object myFileSystem;
private final Method myGetBooleanAttributes;
private StandardMediatorImpl() {
Object fileSystem;
Method getBooleanAttributes;
try {
final Class<?> fsClass = Class.forName("java.io.FileSystem");
final Method getFileSystem = fsClass.getMethod("getFileSystem");
getFileSystem.setAccessible(true);
fileSystem = getFileSystem.invoke(null);
getBooleanAttributes = fsClass.getDeclaredMethod("getBooleanAttributes", File.class);
getBooleanAttributes.setAccessible(true);
}
catch (Throwable t) {
fileSystem = null;
getBooleanAttributes = null;
}
myFileSystem = fileSystem;
myGetBooleanAttributes = getBooleanAttributes;
}
@Override
public FileAttributes getAttributes(@NotNull final String path) throws Exception {
final File file = new File(path);
if (myFileSystem != null) {
final int flags = (Integer)myGetBooleanAttributes.invoke(myFileSystem, file);
if (flags != 0) {
final boolean isDirectory = (flags & BA_DIRECTORY) != 0;
final boolean isSpecial = (flags & (BA_REGULAR | BA_DIRECTORY)) == 0;
return new FileAttributes(isDirectory, false, isSpecial, file.length(), file.lastModified(), file.canWrite());
}
}
else {
if (file.exists()) {
final boolean isDirectory = file.isDirectory();
final boolean isSpecial = !isDirectory && !file.isFile();
return new FileAttributes(isDirectory, false, isSpecial, file.length(), file.lastModified(), file.canWrite());
}
}
return null;
}
@Override
public String resolveSymLink(@NotNull final String path) throws Exception {
return new File(path).getCanonicalPath();
}
@Override
public void setPermissions(@NotNull final String path, final int permissions) throws Exception {
}
}
}
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.dataFlow;
import com.intellij.openapi.progress.ProgressManager;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.CallEnvironment;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.CallInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ControlFlowBuilderUtil;
@@ -77,6 +78,7 @@ public class DFAEngine<E> {
visited[instr.num()] = true;
while (!workList.isEmpty()) {
ProgressManager.checkCanceled();
final Instruction curr = workList.remove();
final int num = curr.num();
final E oldE = info.get(num);