-
-
Notifications
You must be signed in to change notification settings - Fork 955
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
91646dd
commit 78645ec
Showing
14 changed files
with
541 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
32 changes: 32 additions & 0 deletions
32
...system-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFile.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
|
||
} |
27 changes: 27 additions & 0 deletions
27
...-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
|
||
} |
76 changes: 76 additions & 0 deletions
76
...stem-charsets/src/main/java/org/cryptomator/filesystem/charsets/NormalizedNameFolder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
|
||
} |
16 changes: 16 additions & 0 deletions
16
main/filesystem-charsets/src/main/java/org/cryptomator/filesystem/charsets/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
90 changes: 90 additions & 0 deletions
90
...rsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileSystemTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
|
||
} |
48 changes: 48 additions & 0 deletions
48
...em-charsets/src/test/java/org/cryptomator/filesystem/charsets/NormalizedNameFileTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
|
||
} |
Oops, something went wrong.