| /******************************************************************************* |
| * Copyright (c) 2013, 2016 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Chris McGee (IBM) - Bug 380325 - Release filesystem fragment providing Java 7 NIO2 support |
| * Sergey Prigogin (Google) - ongoing development |
| *******************************************************************************/ |
| package org.eclipse.core.internal.filesystem.local.nio; |
| |
| import java.io.IOException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.nio.file.*; |
| import java.nio.file.attribute.DosFileAttributeView; |
| import java.nio.file.attribute.DosFileAttributes; |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileInfo; |
| import org.eclipse.core.filesystem.provider.FileInfo; |
| import org.eclipse.core.internal.filesystem.local.NativeHandler; |
| |
| /** |
| * NativeHandler for file system that supports legacy "DOS" attributes using |
| * only Java 7 API's. It can be used for DOS/Windows file systems. |
| */ |
| public class DosHandler extends NativeHandler { |
| private static final int ATTRIBUTES = EFS.ATTRIBUTE_SYMLINK | EFS.ATTRIBUTE_LINK_TARGET // symbolic link support |
| | EFS.ATTRIBUTE_ARCHIVE | EFS.ATTRIBUTE_READ_ONLY | EFS.ATTRIBUTE_HIDDEN; // standard DOS attributes |
| |
| @Override |
| public FileInfo fetchFileInfo(String fileName) { |
| FileInfo info = new FileInfo(); |
| |
| try { |
| Path path = Paths.get(fileName); |
| |
| // Use canonical file to get the correct case of filename. See bug 431983. |
| Path fileNamePath = path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName(); |
| String canonicalName = fileNamePath == null ? "" : fileNamePath.toString(); //$NON-NLS-1$ |
| info.setName(canonicalName); |
| |
| // To be consistent with the native implementation we do not follow a symbolic link |
| // and return back the information about the target. Instead, we provide the information |
| // about the symbolic link itself whether it exists or not. |
| DosFileAttributes attrs = Files.readAttributes(path, DosFileAttributes.class, LinkOption.NOFOLLOW_LINKS); |
| |
| info.setExists(true); |
| info.setLastModified(attrs.lastModifiedTime().toMillis()); |
| info.setLength(attrs.size()); |
| info.setAttribute(EFS.ATTRIBUTE_ARCHIVE, attrs.isArchive()); |
| info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, attrs.isReadOnly()); |
| info.setAttribute(EFS.ATTRIBUTE_HIDDEN, attrs.isHidden()); |
| if (attrs.isSymbolicLink()) { |
| info.setDirectory(isDirectoryLink(attrs)); |
| info.setAttribute(EFS.ATTRIBUTE_SYMLINK, true); |
| info.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, Files.readSymbolicLink(path).toString()); |
| } else { |
| info.setDirectory(attrs.isDirectory()); |
| } |
| } catch (NoSuchFileException e) { |
| // A non-existing file is not considered an error. |
| } catch (IOException e) { |
| // Leave alone and continue. |
| info.setError(IFileInfo.IO_ERROR); |
| } |
| return info; |
| } |
| |
| private boolean isDirectoryLink(DosFileAttributes attrs) { |
| // Use reflection to call package protected WindowsFileAttributes.isDirectoryLink() method. |
| try { |
| Method method = attrs.getClass().getDeclaredMethod("isDirectoryLink"); //$NON-NLS-1$ |
| method.setAccessible(true); |
| return (Boolean) method.invoke(attrs); |
| } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { |
| return false; |
| } |
| } |
| |
| @Override |
| public int getSupportedAttributes() { |
| return ATTRIBUTES; |
| } |
| |
| @Override |
| public boolean putFileInfo(String fileName, IFileInfo info, int options) { |
| Path path = Paths.get(fileName); |
| // To be consistent with fetchInfo do not following symbolic links to set archive, read only and hidden attributes. |
| DosFileAttributeView view = Files.getFileAttributeView(path, DosFileAttributeView.class, LinkOption.NOFOLLOW_LINKS); |
| try { |
| view.setArchive(info.getAttribute(EFS.ATTRIBUTE_ARCHIVE)); |
| view.setReadOnly(info.getAttribute(EFS.ATTRIBUTE_READ_ONLY)); |
| view.setHidden(info.getAttribute(EFS.ATTRIBUTE_HIDDEN)); |
| } catch (IOException e) { |
| return false; |
| } |
| return true; |
| } |
| } |