mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-18 10:41:26 +00:00
fixes #264
This commit is contained in:
45
main/filesystem-charsets/pom.xml
Normal file
45
main/filesystem-charsets/pom.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2015 Sebastian Stenzel
|
||||
This file is licensed under the terms of the MIT license.
|
||||
See the LICENSE.txt file for more info.
|
||||
|
||||
Contributors:
|
||||
Sebastian Stenzel - initial API and implementation
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-charsets</artifactId>
|
||||
<name>Cryptomator filesystem: Filename charset compatibility layer</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Tests -->
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>commons-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-inmemory</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.filesystem.charsets;
|
||||
|
||||
import java.io.UncheckedIOException;
|
||||
import java.text.Normalizer;
|
||||
import java.text.Normalizer.Form;
|
||||
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.delegating.DelegatingFile;
|
||||
|
||||
class NormalizedNameFile extends DelegatingFile<NormalizedNameFolder> {
|
||||
|
||||
private final Form displayForm;
|
||||
|
||||
public NormalizedNameFile(NormalizedNameFolder parent, File delegate, Form displayForm) {
|
||||
super(parent, delegate);
|
||||
this.displayForm = displayForm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() throws UncheckedIOException {
|
||||
return Normalizer.normalize(super.name(), displayForm);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.filesystem.charsets;
|
||||
|
||||
import java.text.Normalizer.Form;
|
||||
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.cryptomator.filesystem.delegating.DelegatingFileSystem;
|
||||
|
||||
public class NormalizedNameFileSystem extends NormalizedNameFolder implements DelegatingFileSystem {
|
||||
|
||||
public NormalizedNameFileSystem(Folder delegate, Form displayForm) {
|
||||
super(null, delegate, displayForm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Folder getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.filesystem.charsets;
|
||||
|
||||
import java.io.UncheckedIOException;
|
||||
import java.text.Normalizer;
|
||||
import java.text.Normalizer.Form;
|
||||
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.cryptomator.filesystem.delegating.DelegatingFolder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class NormalizedNameFolder extends DelegatingFolder<NormalizedNameFolder, NormalizedNameFile> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NormalizedNameFolder.class);
|
||||
private final Form displayForm;
|
||||
|
||||
public NormalizedNameFolder(NormalizedNameFolder parent, Folder delegate, Form displayForm) {
|
||||
super(parent, delegate);
|
||||
this.displayForm = displayForm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() throws UncheckedIOException {
|
||||
return Normalizer.normalize(super.name(), displayForm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NormalizedNameFile file(String name) throws UncheckedIOException {
|
||||
String nfcName = Normalizer.normalize(name, Form.NFC);
|
||||
String nfdName = Normalizer.normalize(name, Form.NFD);
|
||||
NormalizedNameFile nfcFile = super.file(nfcName);
|
||||
NormalizedNameFile nfdFile = super.file(nfdName);
|
||||
if (!nfcName.equals(nfdName) && nfcFile.exists() && nfdFile.exists()) {
|
||||
LOG.warn("Ambiguous file names \"" + nfcName + "\" (NFC) vs. \"" + nfdName + "\" (NFD). Both files exist. Using \"" + nfcName + "\" (NFC).");
|
||||
} else if (!nfcName.equals(nfdName) && !nfcFile.exists() && nfdFile.exists()) {
|
||||
LOG.info("Moving file from \"" + nfcName + "\" (NFD) to \"" + nfdName + "\" (NFC).");
|
||||
nfdFile.moveTo(nfcFile);
|
||||
}
|
||||
return nfcFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NormalizedNameFile newFile(File delegate) {
|
||||
return new NormalizedNameFile(this, delegate, displayForm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NormalizedNameFolder folder(String name) throws UncheckedIOException {
|
||||
String nfcName = Normalizer.normalize(name, Form.NFC);
|
||||
String nfdName = Normalizer.normalize(name, Form.NFD);
|
||||
NormalizedNameFolder nfcFolder = super.folder(nfcName);
|
||||
NormalizedNameFolder nfdFolder = super.folder(nfdName);
|
||||
if (!nfcName.equals(nfdName) && nfcFolder.exists() && nfdFolder.exists()) {
|
||||
LOG.warn("Ambiguous folder names \"" + nfcName + "\" (NFC) vs. \"" + nfdName + "\" (NFD). Both files exist. Using \"" + nfcName + "\" (NFC).");
|
||||
} else if (!nfcName.equals(nfdName) && !nfcFolder.exists() && nfdFolder.exists()) {
|
||||
LOG.info("Moving folder from \"" + nfcName + "\" (NFD) to \"" + nfdName + "\" (NFC).");
|
||||
nfdFolder.moveTo(nfcFolder);
|
||||
}
|
||||
return nfcFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NormalizedNameFolder newFolder(Folder delegate) {
|
||||
return new NormalizedNameFolder(this, delegate, displayForm);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
/**
|
||||
* Makes sure, the filesystems wrapped by this filesystem work only on UTF-8 encoded file paths using Normalization Form C.
|
||||
* Filesystems wrapping this file system, on the other hand, will get filenames reported in a specified Normalization Form.
|
||||
* It is recommended to use NFD for OS X and NFC for other operating systems.
|
||||
* When looking for a file or folder with a name given in either form, both possibilities are considered
|
||||
* and files/folders stored in NFD are automatically migrated to NFC.
|
||||
*/
|
||||
package org.cryptomator.filesystem.charsets;
|
||||
@@ -0,0 +1,90 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.filesystem.charsets;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.Normalizer.Form;
|
||||
|
||||
import org.cryptomator.filesystem.FileSystem;
|
||||
import org.cryptomator.filesystem.WritableFile;
|
||||
import org.cryptomator.filesystem.inmem.InMemoryFileSystem;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NormalizedNameFileSystemTest {
|
||||
|
||||
@Test
|
||||
public void testFileMigration() {
|
||||
FileSystem inMemoryFs = new InMemoryFileSystem();
|
||||
try (WritableFile writable = inMemoryFs.file("\u006F\u0302").openWritable()) {
|
||||
writable.write(ByteBuffer.allocate(0));
|
||||
}
|
||||
FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC);
|
||||
Assert.assertTrue(normalizationFs.file("\u00F4").exists());
|
||||
Assert.assertTrue(normalizationFs.file("\u006F\u0302").exists());
|
||||
Assert.assertFalse(inMemoryFs.file("\u006F\u0302").exists());
|
||||
Assert.assertTrue(inMemoryFs.file("\u00F4").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFileMigration() {
|
||||
FileSystem inMemoryFs = new InMemoryFileSystem();
|
||||
try (WritableFile writable = inMemoryFs.file("\u00F4").openWritable()) {
|
||||
writable.write(ByteBuffer.allocate(0));
|
||||
}
|
||||
FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC);
|
||||
Assert.assertTrue(normalizationFs.file("\u00F4").exists());
|
||||
Assert.assertTrue(normalizationFs.file("\u006F\u0302").exists());
|
||||
Assert.assertFalse(inMemoryFs.file("\u006F\u0302").exists());
|
||||
Assert.assertTrue(inMemoryFs.file("\u00F4").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFolderMigration() {
|
||||
FileSystem inMemoryFs = new InMemoryFileSystem();
|
||||
inMemoryFs.folder("\u006F\u0302").create();
|
||||
FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC);
|
||||
Assert.assertTrue(normalizationFs.folder("\u00F4").exists());
|
||||
Assert.assertTrue(normalizationFs.folder("\u006F\u0302").exists());
|
||||
Assert.assertFalse(inMemoryFs.folder("\u006F\u0302").exists());
|
||||
Assert.assertTrue(inMemoryFs.folder("\u00F4").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFolderMigration() {
|
||||
FileSystem inMemoryFs = new InMemoryFileSystem();
|
||||
inMemoryFs.folder("\u00F4").create();
|
||||
FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC);
|
||||
Assert.assertTrue(normalizationFs.folder("\u00F4").exists());
|
||||
Assert.assertTrue(normalizationFs.folder("\u006F\u0302").exists());
|
||||
Assert.assertFalse(inMemoryFs.folder("\u006F\u0302").exists());
|
||||
Assert.assertTrue(inMemoryFs.folder("\u00F4").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNfcDisplayNames() {
|
||||
FileSystem inMemoryFs = new InMemoryFileSystem();
|
||||
inMemoryFs.folder("a\u00F4").create();
|
||||
inMemoryFs.folder("b\u006F\u0302").create();
|
||||
FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFC);
|
||||
Assert.assertEquals("a\u00F4", normalizationFs.folder("a\u00F4").name());
|
||||
Assert.assertEquals("b\u00F4", normalizationFs.folder("b\u006F\u0302").name());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNfdDisplayNames() {
|
||||
FileSystem inMemoryFs = new InMemoryFileSystem();
|
||||
inMemoryFs.folder("a\u00F4").create();
|
||||
inMemoryFs.folder("b\u006F\u0302").create();
|
||||
FileSystem normalizationFs = new NormalizedNameFileSystem(inMemoryFs, Form.NFD);
|
||||
Assert.assertEquals("a\u006F\u0302", normalizationFs.folder("a\u00F4").name());
|
||||
Assert.assertEquals("b\u006F\u0302", normalizationFs.folder("b\u006F\u0302").name());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.filesystem.charsets;
|
||||
|
||||
import java.text.Normalizer.Form;
|
||||
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class NormalizedNameFileTest {
|
||||
|
||||
private File delegateNfc;
|
||||
private File delegateNfd;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
delegateNfc = Mockito.mock(File.class);
|
||||
delegateNfd = Mockito.mock(File.class);
|
||||
Mockito.when(delegateNfc.name()).thenReturn("\u00C5");
|
||||
Mockito.when(delegateNfd.name()).thenReturn("\u0041\u030A");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNameInNfc() {
|
||||
File file1 = new NormalizedNameFile(null, delegateNfc, Form.NFC);
|
||||
File file2 = new NormalizedNameFile(null, delegateNfd, Form.NFC);
|
||||
Assert.assertEquals("\u00C5", file1.name());
|
||||
Assert.assertEquals("\u00C5", file2.name());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNameInNfd() {
|
||||
File file1 = new NormalizedNameFile(null, delegateNfc, Form.NFD);
|
||||
File file2 = new NormalizedNameFile(null, delegateNfd, Form.NFD);
|
||||
Assert.assertEquals("\u0041\u030A", file1.name());
|
||||
Assert.assertEquals("\u0041\u030A", file2.name());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.filesystem.charsets;
|
||||
|
||||
import java.text.Normalizer.Form;
|
||||
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class NormalizedNameFolderTest {
|
||||
|
||||
private Folder delegate;
|
||||
private File delegateSubFileNfc;
|
||||
private File delegateSubFileNfd;
|
||||
private Folder delegateSubFolderNfc;
|
||||
private Folder delegateSubFolderNfd;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
delegate = Mockito.mock(Folder.class);
|
||||
delegateSubFileNfc = Mockito.mock(File.class);
|
||||
delegateSubFileNfd = Mockito.mock(File.class);
|
||||
Mockito.when(delegate.file("\u00C5")).thenReturn(delegateSubFileNfc);
|
||||
Mockito.when(delegateSubFileNfc.name()).thenReturn("\u00C5");
|
||||
Mockito.when(delegate.file("\u0041\u030A")).thenReturn(delegateSubFileNfd);
|
||||
Mockito.when(delegateSubFileNfd.name()).thenReturn("\u0041\u030A");
|
||||
delegateSubFolderNfc = Mockito.mock(Folder.class);
|
||||
delegateSubFolderNfd = Mockito.mock(Folder.class);
|
||||
Mockito.when(delegate.folder("\u00F4")).thenReturn(delegateSubFolderNfc);
|
||||
Mockito.when(delegateSubFolderNfc.name()).thenReturn("\u00F4");
|
||||
Mockito.when(delegate.folder("\u006F\u0302")).thenReturn(delegateSubFolderNfd);
|
||||
Mockito.when(delegateSubFolderNfd.name()).thenReturn("\u006F\u0302");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNameInNfc() {
|
||||
Folder folder1 = new NormalizedNameFolder(null, delegateSubFolderNfc, Form.NFC);
|
||||
Folder folder2 = new NormalizedNameFolder(null, delegateSubFolderNfd, Form.NFC);
|
||||
Assert.assertEquals("\u00F4", folder1.name());
|
||||
Assert.assertEquals("\u00F4", folder2.name());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayNameInNfd() {
|
||||
Folder folder1 = new NormalizedNameFolder(null, delegateSubFolderNfc, Form.NFD);
|
||||
Folder folder2 = new NormalizedNameFolder(null, delegateSubFolderNfd, Form.NFD);
|
||||
Assert.assertEquals("\u006F\u0302", folder1.name());
|
||||
Assert.assertEquals("\u006F\u0302", folder2.name());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFolderMigration1() {
|
||||
Mockito.when(delegateSubFolderNfc.exists()).thenReturn(true);
|
||||
Mockito.when(delegateSubFolderNfd.exists()).thenReturn(false);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
Folder sub1 = folder.folder("\u00F4");
|
||||
Folder sub2 = folder.folder("\u006F\u0302");
|
||||
Mockito.verify(delegateSubFolderNfd, Mockito.never()).moveTo(Mockito.any());
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFolderMigration2() {
|
||||
Mockito.when(delegateSubFolderNfc.exists()).thenReturn(true);
|
||||
Mockito.when(delegateSubFolderNfd.exists()).thenReturn(true);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
Folder sub1 = folder.folder("\u00F4");
|
||||
Folder sub2 = folder.folder("\u006F\u0302");
|
||||
Mockito.verify(delegateSubFolderNfd, Mockito.never()).moveTo(Mockito.any());
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFolderMigration3() {
|
||||
Mockito.when(delegateSubFolderNfc.exists()).thenReturn(false);
|
||||
Mockito.when(delegateSubFolderNfd.exists()).thenReturn(false);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
Folder sub1 = folder.folder("\u00F4");
|
||||
Folder sub2 = folder.folder("\u006F\u0302");
|
||||
Mockito.verify(delegateSubFolderNfd, Mockito.never()).moveTo(Mockito.any());
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFolderMigration() {
|
||||
Mockito.when(delegateSubFolderNfc.exists()).thenReturn(false);
|
||||
Mockito.when(delegateSubFolderNfd.exists()).thenReturn(true);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
Folder sub1 = folder.folder("\u00F4");
|
||||
Mockito.verify(delegateSubFolderNfd).moveTo(delegateSubFolderNfc);
|
||||
Folder sub2 = folder.folder("\u006F\u0302");
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFileMigration1() {
|
||||
Mockito.when(delegateSubFileNfc.exists()).thenReturn(true);
|
||||
Mockito.when(delegateSubFileNfd.exists()).thenReturn(false);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
File sub1 = folder.file("\u00C5");
|
||||
File sub2 = folder.file("\u0041\u030A");
|
||||
Mockito.verify(delegateSubFileNfd, Mockito.never()).moveTo(Mockito.any());
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFileMigration2() {
|
||||
Mockito.when(delegateSubFileNfc.exists()).thenReturn(true);
|
||||
Mockito.when(delegateSubFileNfd.exists()).thenReturn(true);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
File sub1 = folder.file("\u00C5");
|
||||
File sub2 = folder.file("\u0041\u030A");
|
||||
Mockito.verify(delegateSubFileNfd, Mockito.never()).moveTo(Mockito.any());
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFileMigration3() {
|
||||
Mockito.when(delegateSubFileNfc.exists()).thenReturn(false);
|
||||
Mockito.when(delegateSubFileNfd.exists()).thenReturn(false);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
File sub1 = folder.file("\u00C5");
|
||||
File sub2 = folder.file("\u0041\u030A");
|
||||
Mockito.verify(delegateSubFileNfd, Mockito.never()).moveTo(Mockito.any());
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileMigration() {
|
||||
Mockito.when(delegateSubFileNfc.exists()).thenReturn(false);
|
||||
Mockito.when(delegateSubFileNfd.exists()).thenReturn(true);
|
||||
Folder folder = new NormalizedNameFolder(null, delegate, Form.NFC);
|
||||
File sub1 = folder.file("\u00C5");
|
||||
Mockito.verify(delegateSubFileNfd).moveTo(delegateSubFileNfc);
|
||||
File sub2 = folder.file("\u0041\u030A");
|
||||
Assert.assertSame(sub1, sub2);
|
||||
}
|
||||
|
||||
}
|
||||
22
main/filesystem-charsets/src/test/resources/log4j2.xml
Normal file
22
main/filesystem-charsets/src/test/resources/log4j2.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<Configuration status="WARN">
|
||||
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%16d %-5p [%c{1}:%L] %m%n" />
|
||||
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="ACCEPT" />
|
||||
</Console>
|
||||
<Console name="StdErr" target="SYSTEM_ERR">
|
||||
<PatternLayout pattern="%16d %-5p [%c{1}:%L] %m%n" />
|
||||
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY" />
|
||||
</Console>
|
||||
</Appenders>
|
||||
|
||||
<Loggers>
|
||||
<Root level="DEBUG">
|
||||
<AppenderRef ref="Console" />
|
||||
<AppenderRef ref="StdErr" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
|
||||
</Configuration>
|
||||
@@ -20,6 +20,10 @@
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-charsets</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-crypto</artifactId>
|
||||
|
||||
@@ -4,11 +4,13 @@ import static org.cryptomator.common.test.TempFilesRemovedOnShutdown.createTempD
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.text.Normalizer.Form;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.cryptomator.filesystem.FileSystem;
|
||||
import org.cryptomator.filesystem.charsets.NormalizedNameFileSystem;
|
||||
import org.cryptomator.filesystem.crypto.CryptoEngineTestModule;
|
||||
import org.cryptomator.filesystem.crypto.CryptoFileSystemDelegate;
|
||||
import org.cryptomator.filesystem.crypto.CryptoFileSystemTestComponent;
|
||||
@@ -35,8 +37,10 @@ class FileSystemFactories implements Iterable<FileSystemFactory> {
|
||||
add("ShorteningFileSystem > InMemoryFileSystem", this::createShorteningFileSystemInMemory);
|
||||
add("StatsFileSystem > NioFileSystem", this::createStatsFileSystemNio);
|
||||
add("StatsFileSystem > InMemoryFileSystem", this::createStatsFileSystemInMemory);
|
||||
add("StatsFileSystem > CryptoFileSystem > ShorteningFileSystem > InMemoryFileSystem", this::createCompoundFileSystemInMemory);
|
||||
add("StatsFileSystem > CryptoFileSystem > ShorteningFileSystem > NioFileSystem", this::createCompoundFileSystemNio);
|
||||
add("NormalizingFileSystem > NioFileSystem", this::createNormalizingFileSystemNio);
|
||||
add("NormalizingFileSystem > InMemoryFileSystem", this::createNormalizingFileSystemInMemory);
|
||||
add("StatsFileSystem > NormalizingFileSystem > CryptoFileSystem > ShorteningFileSystem > InMemoryFileSystem", this::createCompoundFileSystemInMemory);
|
||||
add("StatsFileSystem > NormalizingFileSystem > CryptoFileSystem > ShorteningFileSystem > NioFileSystem", this::createCompoundFileSystemNio);
|
||||
}
|
||||
|
||||
private FileSystem createCryptoFileSystemInMemory() {
|
||||
@@ -63,6 +67,14 @@ class FileSystemFactories implements Iterable<FileSystemFactory> {
|
||||
return createStatsFileSystem(createInMemoryFileSystem());
|
||||
}
|
||||
|
||||
private FileSystem createNormalizingFileSystemNio() {
|
||||
return createNormalizingFileSystem(createInMemoryFileSystem());
|
||||
}
|
||||
|
||||
private FileSystem createNormalizingFileSystemInMemory() {
|
||||
return createNormalizingFileSystem(createInMemoryFileSystem());
|
||||
}
|
||||
|
||||
private FileSystem createCompoundFileSystemNio() {
|
||||
return createCompoundFileSystem(createNioFileSystem());
|
||||
}
|
||||
@@ -84,13 +96,17 @@ class FileSystemFactories implements Iterable<FileSystemFactory> {
|
||||
}
|
||||
|
||||
private FileSystem createCompoundFileSystem(FileSystem delegate) {
|
||||
return createStatsFileSystem(createCryptoFileSystem(createShorteningFileSystem(delegate)));
|
||||
return createStatsFileSystem(createNormalizingFileSystem(createCryptoFileSystem(createShorteningFileSystem(delegate))));
|
||||
}
|
||||
|
||||
private FileSystem createStatsFileSystem(FileSystem delegate) {
|
||||
return new StatsFileSystem(delegate);
|
||||
}
|
||||
|
||||
private FileSystem createNormalizingFileSystem(FileSystem delegate) {
|
||||
return new NormalizedNameFileSystem(delegate, Form.NFC);
|
||||
}
|
||||
|
||||
private FileSystem createCryptoFileSystem(FileSystem delegate) {
|
||||
CRYPTO_FS_COMP.cryptoFileSystemFactory().initializeNew(delegate, "aPassphrase");
|
||||
return CRYPTO_FS_COMP.cryptoFileSystemFactory().unlockExisting(delegate, "aPassphrase", Mockito.mock(CryptoFileSystemDelegate.class));
|
||||
|
||||
@@ -80,6 +80,11 @@
|
||||
<artifactId>filesystem-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-charsets</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-nio</artifactId>
|
||||
@@ -286,6 +291,7 @@
|
||||
<module>frontend-api</module>
|
||||
<module>frontend-webdav</module>
|
||||
<module>ui</module>
|
||||
<module>filesystem-charsets</module>
|
||||
</modules>
|
||||
|
||||
<profiles>
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-crypto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-charsets</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-stats</artifactId>
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.cryptomator.common.LazyInitializer;
|
||||
import org.cryptomator.common.Optionals;
|
||||
import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
||||
import org.cryptomator.filesystem.FileSystem;
|
||||
import org.cryptomator.filesystem.charsets.NormalizedNameFileSystem;
|
||||
import org.cryptomator.filesystem.crypto.CryptoFileSystemDelegate;
|
||||
import org.cryptomator.filesystem.crypto.CryptoFileSystemFactory;
|
||||
import org.cryptomator.filesystem.nio.NioFileSystem;
|
||||
@@ -126,7 +127,8 @@ public class Vault implements CryptoFileSystemDelegate {
|
||||
FileSystem fs = getNioFileSystem();
|
||||
FileSystem shorteningFs = shorteningFileSystemFactory.get(fs);
|
||||
FileSystem cryptoFs = cryptoFileSystemFactory.unlockExisting(shorteningFs, passphrase, this);
|
||||
StatsFileSystem statsFs = new StatsFileSystem(cryptoFs);
|
||||
FileSystem normalizingFs = new NormalizedNameFileSystem(cryptoFs, SystemUtils.IS_OS_MAC_OSX ? Form.NFD : Form.NFC);
|
||||
StatsFileSystem statsFs = new StatsFileSystem(normalizingFs);
|
||||
statsFileSystem = Optional.of(statsFs);
|
||||
String contextPath = StringUtils.prependIfMissing(mountName, "/");
|
||||
Frontend frontend = frontendFactory.create(statsFs, contextPath);
|
||||
|
||||
Reference in New Issue
Block a user