diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/AbstractEasyDokanFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractEasyDokanFileSystem.java new file mode 100644 index 0000000..352f217 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractEasyDokanFileSystem.java @@ -0,0 +1,69 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.NativeName; +import dev.dokan.dokan_java.FileSystemInformation; +import dev.dokan.dokan_java.NotImplemented; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public abstract class AbstractEasyDokanFileSystem implements EasyDokanFileSystem { + + private final Set notImplementedMethods; + private final ForwardingFileSystem lowLevelFS; + + public AbstractEasyDokanFileSystem(FileSystemInformation fileSystemInformation) { + this.notImplementedMethods = Arrays.stream(getClass().getMethods()) + .filter(method -> method.getAnnotation(NotImplemented.class) != null) + .map((method) -> getNativeName(method)) + .collect(Collectors.toSet()); + + this.lowLevelFS = new ForwardingFileSystem(fileSystemInformation, this.notImplementedMethods, this); + } + + private String getNativeName(Method method) { + Method annotated = getAnnotatedMethod(NativeName.class, method); + + if(annotated == null) { + return method.getName(); + } + return annotated.getAnnotation(NativeName.class).value(); + } + + private Method getAnnotatedMethod(Class annotation, Method method) { + return getAnnotatedMethod(annotation, method.getDeclaringClass(), method.getName(), method.getParameterTypes()); + } + + private Method getAnnotatedMethod(Class annotation, + Class inClass, + String methodName, + Class... parameterTypes) { + + Method result; + try { + result = inClass.getMethod(methodName, parameterTypes); + } catch(NoSuchMethodException e) { + return null; + } + + if(result.isAnnotationPresent(annotation)) { + return result; + } + + Class superClass = inClass.getSuperclass(); + if(superClass != null) { + result = getAnnotatedMethod(annotation, superClass, methodName, parameterTypes); + } + + if(result != null) { + return result; + } + + return Arrays.stream(inClass.getInterfaces()) + .map((cInterface) -> getAnnotatedMethod(annotation, cInterface, methodName, parameterTypes)) + .findFirst().orElse(null); + } +} diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java new file mode 100644 index 0000000..1758715 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java @@ -0,0 +1,217 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.FileSystemInformation; +import dev.dokan.dokan_java.NotImplemented; +import dev.dokan.dokan_java.constants.microsoft.CreateOption; +import dev.dokan.dokan_java.constants.microsoft.CreationDisposition; +import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.constants.microsoft.FileShareAccess; +import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.structure.filesecurity.SelfRelativeSecurityDescriptor; + +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; +import java.util.Collection; + +public class EasyDokanFileSystemStub extends AbstractEasyDokanFileSystem { + + public EasyDokanFileSystemStub(FileSystemInformation fileSystemInformation) { + super(fileSystemInformation); + } + + @NotImplemented + @Override + public void createHandle(Path absolutePath, + String relativePath, + EasyDokanIOSecurityContext securityContext, + DesiredAccessMask desiredAccess, + EnumIntegerSet fileAttributes, + EnumIntegerSet shareAccess, + CreationDisposition creationDisposition, + EnumIntegerSet createOptions, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void cleanup(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void closeHandle(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public byte[] readFile(Path absolutePath, + String relativePath, + long offset, + int readLength, + DokanFileHandle dokanFileHandle) { + return new byte[0]; + } + + @NotImplemented + @Override + public int writeFile(Path absolutePath, + String relativePath, + byte[] buffer, + long offset, + DokanFileHandle dokanFileHandle) { + return 0; + } + + @NotImplemented + @Override + public void flush(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public EasyFileInfo getFileInformation(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public Collection findFiles(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public Collection findFilesWithPattern(Path absolutePath, + String relativePath, + String pattern, + DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public void setFileAttributes(Path absolutePath, + String relativePath, + EnumIntegerSet fileAttributes, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void setFileTime(Path absolutePath, + String relativePath, + FileTime creationTime, + FileTime lastAccessTime, + FileTime lastWriteTime, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void prepareDeleteFile(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void prepareDeleteDirectory(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void moveFile(Path sourceAbsolutePath, + String sourceRelativePath, + Path destinationAbsolutePath, + String destinationRelativePath, + boolean replaceIfExisting, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void setEndOfFile(Path absolutePath, String relativePath, long fileSize, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void setAllocationSize(Path absolutePath, + String relativePath, + long allocationSize, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void lockFile(Path absolutePath, + String relativePath, + long lockOffset, + long lockLength, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void unlockFile(Path absolutePath, + String relativePath, + long lockOffset, + long lockLength, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public DiskSpaceInfo getDiskSpaceInfo(DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public VolumeInformation getVolumeInformation(DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public void mounted(DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void unmounted(DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public SelfRelativeSecurityDescriptor getFileSecurity(Path absolutePath, + String relativePath, + DesiredAccessMask requestedDescriptorInfo, + int availableLength, + DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public void setFileSecurity(Path absolutePath, + String relativePath, + DesiredAccessMask suppliedDescriptorInfo, + SelfRelativeSecurityDescriptor securityDescriptor, + int availableLength, + DokanFileHandle dokanFileHandle) { + + } +} diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/ForwardingFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/ForwardingFileSystem.java new file mode 100644 index 0000000..2cbcb75 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/ForwardingFileSystem.java @@ -0,0 +1,241 @@ +package dev.dokan.dokan_java.wrappers; + + +import com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WinBase; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.LongByReference; +import dev.dokan.dokan_java.AbstractDokanFileSystem; +import dev.dokan.dokan_java.DokanException; +import dev.dokan.dokan_java.DokanOperations; +import dev.dokan.dokan_java.FileSystemInformation; +import dev.dokan.dokan_java.constants.microsoft.Win32ErrorCodes; +import dev.dokan.dokan_java.structure.ByHandleFileInformation; +import dev.dokan.dokan_java.structure.DokanFileInfo; +import dev.dokan.dokan_java.structure.DokanIOSecurityContext; + +import java.nio.file.Path; +import java.util.Set; + + +public class ForwardingFileSystem extends AbstractDokanFileSystem { + + private final Set notImplementedMethods; + private final AbstractEasyDokanFileSystem creator; + + public ForwardingFileSystem(FileSystemInformation fileSystemInformation, Set notImplementedMethods, AbstractEasyDokanFileSystem target) { + super(fileSystemInformation); + this.notImplementedMethods = notImplementedMethods; + this.creator = target; + } + + @Override + public boolean isImplemented(String funcName) { + return !this.notImplementedMethods.contains(funcName); + } + + + @Override + public int zwCreateFile(WString rawPath, DokanIOSecurityContext securityContext, int rawDesiredAccess, int rawFileAttributes, int rawShareAccess, int rawCreateDisposition, int rawCreateOptions, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public void cleanup(WString rawPath, DokanFileInfo dokanFileInfo) { + + } + + @Override + public void closeFile(WString rawPath, DokanFileInfo dokanFileInfo) { + + } + + @Override + public int readFile(WString rawPath, + Pointer rawBuffer, + int rawBufferLength, + IntByReference rawReadLength, + long rawOffset, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int writeFile(WString rawPath, + Pointer rawBuffer, + int rawNumberOfBytesToWrite, + IntByReference rawNumberOfBytesWritten, + long rawOffset, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int flushFileBuffers(WString rawPath, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getFileInformation(WString fileName, + ByHandleFileInformation handleFileInfo, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int findFiles(WString rawPath, + DokanOperations.FillWin32FindData rawFillFindData, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int findFilesWithPattern(WString fileName, + WString searchPattern, + DokanOperations.FillWin32FindData rawFillFindData, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setFileAttributes(WString rawPath, int rawAttributes, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setFileTime(WString rawPath, + WinBase.FILETIME rawCreationTime, + WinBase.FILETIME rawLastAccessTime, + WinBase.FILETIME rawLastWriteTime, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int deleteFile(WString rawPath, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int deleteDirectory(WString rawPath, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int moveFile(WString rawPath, + WString rawNewFileName, + boolean rawReplaceIfExisting, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setEndOfFile(WString rawPath, long rawByteOffset, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setAllocationSize(WString rawPath, long rawLength, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int lockFile(WString rawPath, long rawByteOffset, long rawLength, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int unlockFile(WString rawPath, long rawByteOffset, long rawLength, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getDiskFreeSpace(LongByReference freeBytesAvailable, + LongByReference totalNumberOfBytes, + LongByReference totalNumberOfFreeBytes, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getVolumeInformation(Pointer rawVolumeNameBuffer, + int rawVolumeNameSize, + IntByReference rawVolumeSerialNumber, + IntByReference rawMaximumComponentLength, + IntByReference rawFileSystemFlags, + Pointer rawFileSystemNameBuffer, + int rawFileSystemNameSize, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int mounted(DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int unmounted(DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getFileSecurity(WString rawPath, + int rawSecurityInformation, + Pointer rawSecurityDescriptor, + int rawSecurityDescriptorLength, + IntByReference rawSecurityDescriptorLengthNeeded, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setFileSecurity(WString rawPath, + int rawSecurityInformation, + Pointer rawSecurityDescriptor, + int rawSecurityDescriptorLength, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public void fillWin32FindData(WinBase.WIN32_FIND_DATA rawFillFindData, DokanFileInfo dokanFileInfo) { + + } + + @Override + public int findStreams(WString rawPath, + DokanOperations.FillWin32FindStreamData rawFillFindData, + DokanFileInfo dokanFileInfo) { + return 0; + } + + private int handleException(DokanException exc) { //TODO Reformat to allow any kind of exception + if (exc == null) { + return Win32ErrorCodes.ERROR_GEN_FAILURE; + } + + if (exc.getErrorCode() == Integer.MIN_VALUE) { + //TODO + } + //TODO Log + return exc.getErrorCode(); + } + + private String resolveRelativePath(WString path) { + return resolveRelativePath(path.toString()); + } + + private String resolveRelativePath(String path) { + return path; + } + + private Path resolveAbsolutePath(WString path) { + return resolveAbsolutePath(path.toString()); + } + + private Path resolveAbsolutePath(String path) { + return null; //TODO Implement + } +} \ No newline at end of file