/* * JBoss, Home of Professional Open Source. * Copyright 2011, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.controller.persistence; import static java.nio.file.attribute.PosixFilePermission.GROUP_READ; import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ; import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE; import static java.nio.file.attribute.PosixFilePermission.OWNER_READ; import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.AclEntry; import java.nio.file.attribute.AclEntryFlag; import java.nio.file.attribute.AclEntryPermission; import java.nio.file.attribute.AclEntryType; import java.nio.file.attribute.AclFileAttributeView; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.UserPrincipal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.jboss.as.controller.PathAddress; import org.jboss.dmr.ModelNode; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> */ public class PersistanceResourceTestCase { File configsDir; File standardDir; File externalDir; File historyDir; File currentHistoryDir; File standardFile; File externalFile; File lastFile; File initialFile; File bootFile; @Before public void createDirectoriesAndFiles() throws Exception { File tgt = new File("target"); if (!tgt.exists()) { Assert.fail("target/ does not exist"); } configsDir = createDir(tgt, "persistence-test-configs"); standardDir = createDir(configsDir, "standard"); externalDir = createDir(configsDir, "external"); standardFile = createFile(standardDir, "standard.xml", "std"); externalFile = createFile(externalDir, "standard.xml", "ext"); historyDir = new File(standardDir, "standard_xml_history"); lastFile = new File(historyDir, "standard.last.xml"); bootFile = new File(historyDir, "standard.boot.xml"); initialFile = new File(historyDir, "standard.initial.xml"); currentHistoryDir = new File(historyDir, "current"); } @After public void deleteDirectoriesAndFiles() throws Exception { delete(configsDir); } @Test public void testFileResource() throws Exception { assertFileContents(standardFile, "std"); TestFileResourcePersister persister = new TestFileResourcePersister(standardFile); store(persister, "One"); assertFileContents(standardFile, "One"); store(persister, "Two"); assertFileContents(standardFile, "Two"); Assert.assertFalse(historyDir.exists()); } @Test public void testDefaultPersistentConfigurationFile() throws Exception { assertFileContents(standardFile, "std"); Assert.assertFalse(historyDir.exists()); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", null, true); Assert.assertEquals(standardFile.getCanonicalPath(), configurationFile.getBootFile().getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "std", "std", "std"); store(persister, "One"); checkFiles(null, "One", "std", "std", "One", "std"); store(persister, "Two"); checkFiles(null, "Two", "std", "std", "Two", "std", "One"); store(persister, "Three"); checkFiles(null, "Three", "std", "std", "Three", "std", "One", "Two"); // "Reboot" configurationFile = new ConfigurationFile(standardDir, "standard.xml", null, true); Assert.assertEquals(standardFile.getCanonicalPath(), configurationFile.getBootFile().getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "Three", "std", "Three", "Three"); store(persister, "Four"); checkFiles(null, "Four", "std", "Three", "Four", "Three"); } @Test public void testOtherPersistentConfigurationFile() throws Exception { assertFileContents(standardFile, "std"); createFile(standardDir, "test.xml", "non-std"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", "test.xml", true); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(standardDir, "test.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles("test", "non-std", "non-std", "non-std", "non-std"); store(persister, "One"); checkFiles("test", "One", "non-std", "non-std", "One", "non-std"); store(persister, "Two"); checkFiles("test", "Two", "non-std", "non-std", "Two", "non-std", "One"); store(persister, "Three"); checkFiles("test", "Three", "non-std", "non-std", "Three", "non-std", "One", "Two"); // "Reboot" configurationFile = new ConfigurationFile(standardDir, "standard.xml", "test.xml", true); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(standardFile.getCanonicalFile().getParentFile(), "test.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles("test", "Three", "non-std", "Three", "Three"); store(persister, "Four"); checkFiles("test", "Four", "non-std", "Three", "Four", "Three"); } @Test public void testPersistentConfigurationFileFromBackupUsingThePrefix() throws Exception { //Boot with boot bootFile.getParentFile().mkdirs(); createFile(historyDir, bootFile.getName(), "boot"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", "boot", true); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(bootFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "boot", "boot", "boot", "boot"); store(persister, "One"); checkFiles(null, "One", "boot", "boot", "One", "boot"); store(persister, "Two"); checkFiles(null, "Two", "boot", "boot", "Two", "boot", "One"); store(persister, "Three"); checkFiles(null, "Three", "boot", "boot", "Three", "boot", "One", "Two"); // "Reboot" with last configurationFile = new ConfigurationFile(standardDir, "standard.xml", "last", true); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(lastFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "Three", "boot", "Three", "Three"); store(persister, "Four"); checkFiles(null, "Four", "boot", "Three", "Four", "Three"); // "Reboot" with initial configurationFile = new ConfigurationFile(standardDir, "standard.xml", "initial", true); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(initialFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "boot", "boot", "boot", "boot"); store(persister, "Four"); checkFiles(null, "Four", "boot", "boot", "Four", "boot"); store(persister, "Five"); checkFiles(null, "Five", "boot", "boot", "Five", "boot", "Four"); store(persister, "Six"); checkFiles(null, "Six", "boot", "boot", "Six", "boot", "Four", "Five"); // "Reboot" with v2 configurationFile = new ConfigurationFile(standardDir, "standard.xml", "v2", true); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(currentHistoryDir, "standard.v2.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "Four", "boot", "Four", "Four"); } @Test public void testPersistentConfigurationFileFromBackupUsingTheRelativePath() throws Exception { //Boot with boot bootFile.getParentFile().mkdirs(); createFile(historyDir, bootFile.getName(), "boot"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/standard.boot.xml", true); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(bootFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "boot", "boot", "boot", "boot"); store(persister, "One"); checkFiles(null, "One", "boot", "boot", "One", "boot"); store(persister, "Two"); checkFiles(null, "Two", "boot", "boot", "Two", "boot", "One"); store(persister, "Three"); checkFiles(null, "Three", "boot", "boot", "Three", "boot", "One", "Two"); // "Reboot" with last configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/standard.last.xml", true); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(lastFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "Three", "boot", "Three", "Three"); store(persister, "Four"); checkFiles(null, "Four", "boot", "Three", "Four", "Three"); // "Reboot" with initial configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/standard.initial.xml", true); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(initialFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "boot", "boot", "boot", "boot"); store(persister, "Four"); checkFiles(null, "Four", "boot", "boot", "Four", "boot"); store(persister, "Five"); checkFiles(null, "Five", "boot", "boot", "Five", "boot", "Four"); store(persister, "Six"); checkFiles(null, "Six", "boot", "boot", "Six", "boot", "Four", "Five"); // "Reboot" with v2 configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/current/standard.v2.xml", true); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(currentHistoryDir, "standard.v2.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "Four", "boot", "Four", "Four"); } @Test(expected = IllegalStateException.class) public void testPersistentBadRawName() { new ConfigurationFile(standardDir, "standard.xml", "crap.xml", true); } @Test(expected = IllegalStateException.class) public void testPersistentNameFromOutsideConfigDirectory() throws Exception { File file = createFile(externalDir, "standard.xml", "test"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", file.getAbsolutePath(), true); } @Test public void testDefaultNonPersistentConfigurationFile() throws Exception { assertFileContents(standardFile, "std"); Assert.assertFalse(historyDir.exists()); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", null, false); Assert.assertEquals(standardFile.getCanonicalPath(), configurationFile.getBootFile().getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "std", "std", "std"); store(persister, "One"); checkFiles(null, "std", "std", "std", "One", "std"); store(persister, "Two"); checkFiles(null, "std", "std", "std", "Two", "std", "One"); store(persister, "Three"); checkFiles(null, "std", "std", "std", "Three", "std", "One", "Two"); // "Reboot" configurationFile = new ConfigurationFile(standardDir, "standard.xml", null, false); Assert.assertEquals(standardFile.getCanonicalPath(), configurationFile.getBootFile().getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "std", "std", "std"); store(persister, "Four"); checkFiles(null, "std", "std", "std", "Four", "std"); } @Test public void testOtherNonPersistentConfigurationFile() throws Exception { assertFileContents(standardFile, "std"); createFile(standardDir, "test.xml", "non-std"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", "test.xml", false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(standardDir, "test.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles("test", "non-std", "non-std", "non-std", "non-std"); store(persister, "One"); checkFiles("test", "non-std", "non-std", "non-std", "One", "non-std"); store(persister, "Two"); checkFiles("test", "non-std", "non-std", "non-std", "Two", "non-std", "One"); store(persister, "Three"); checkFiles("test", "non-std", "non-std", "non-std", "Three", "non-std", "One", "Two"); // "Reboot" configurationFile = new ConfigurationFile(standardDir, "standard.xml", "test.xml", false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(standardFile.getCanonicalFile().getParentFile(), "test.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles("test", "non-std", "non-std", "non-std", "non-std"); store(persister, "Four"); checkFiles("test", "non-std", "non-std", "non-std", "Four", "non-std"); } @Test public void testNonPersistentConfigurationFileFromBackupUsingThePrefix() throws Exception { //Boot with boot bootFile.getParentFile().mkdirs(); createFile(historyDir, bootFile.getName(), "boot"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", "boot", false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(bootFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "boot", "boot"); store(persister, "One"); checkFiles(null, "std", "boot", "boot", "One", "boot"); store(persister, "Two"); checkFiles(null, "std", "boot", "boot", "Two", "boot", "One"); store(persister, "Three"); checkFiles(null, "std", "boot", "boot", "Three", "boot", "One", "Two"); // "Reboot" with last configurationFile = new ConfigurationFile(standardDir, "standard.xml", "last", false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(lastFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "Three", "Three"); store(persister, "Four"); checkFiles(null, "std", "boot", "Three", "Four", "Three"); // "Reboot" with initial configurationFile = new ConfigurationFile(standardDir, "standard.xml", "initial", false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(initialFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "boot", "boot"); store(persister, "Four"); checkFiles(null, "std", "boot", "boot", "Four", "boot"); store(persister, "Five"); checkFiles(null, "std", "boot", "boot", "Five", "boot", "Four"); store(persister, "Six"); checkFiles(null, "std", "boot", "boot", "Six", "boot", "Four", "Five"); // "Reboot" with v2 configurationFile = new ConfigurationFile(standardDir, "standard.xml", "v2", false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(currentHistoryDir, "standard.v2.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "Four", "Four"); } @Test public void testNonPersistentConfigurationFileFromBackupUsingTheRelativePath() throws Exception { //Boot with boot bootFile.getParentFile().mkdirs(); createFile(historyDir, bootFile.getName(), "boot"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/standard.boot.xml", false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(bootFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "boot", "boot"); store(persister, "One"); checkFiles(null, "std", "boot", "boot", "One", "boot"); store(persister, "Two"); checkFiles(null, "std", "boot", "boot", "Two", "boot", "One"); store(persister, "Three"); checkFiles(null, "std", "boot", "boot", "Three", "boot", "One", "Two"); // "Reboot" with last configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/standard.last.xml", false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(lastFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "Three", "Three"); store(persister, "Four"); checkFiles(null, "std", "boot", "Three", "Four", "Three"); // "Reboot" with initial configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/standard.initial.xml", false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(initialFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "boot", "boot"); store(persister, "Four"); checkFiles(null, "std", "boot", "boot", "Four", "boot"); store(persister, "Five"); checkFiles(null, "std", "boot", "boot", "Five", "boot", "Four"); store(persister, "Six"); checkFiles(null, "std", "boot", "boot", "Six", "boot", "Four", "Five"); // "Reboot" with v2 configurationFile = new ConfigurationFile(standardDir, "standard.xml", "standard_xml_history/current/standard.v2.xml", false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(new File(currentHistoryDir, "standard.v2.xml").getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "boot", "Four", "Four"); } @Test(expected = IllegalStateException.class) public void testNonPersistentBadRawName() { new ConfigurationFile(standardDir, "standard.xml", "crap.xml", false); } @Test public void testNonPersistentNameFromOutsideConfigDirectory() throws Exception { assertFileContents(externalFile, "ext"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", externalFile.getCanonicalPath(), false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(externalFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "ext", "ext", "ext"); assertFileContents(externalFile, "ext"); store(persister, "One"); checkFiles(null, "std", "ext", "ext", "One", "ext"); assertFileContents(externalFile, "ext"); store(persister, "Two"); checkFiles(null, "std", "ext", "ext", "Two", "ext", "One"); assertFileContents(externalFile, "ext"); store(persister, "Three"); checkFiles(null, "std", "ext", "ext", "Three", "ext", "One", "Two"); assertFileContents(externalFile, "ext"); externalFile.delete(); createFile(externalDir, externalFile.getName(), "ext2"); // "Reboot" configurationFile = new ConfigurationFile(standardDir, "standard.xml", externalFile.getCanonicalPath(), false); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(externalFile.getCanonicalPath(), bootingFile.getCanonicalPath()); persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "ext", "ext2", "ext2"); assertFileContents(externalFile, "ext2"); store(persister, "Four"); checkFiles(null, "std", "ext", "ext2", "Four", "ext2"); assertFileContents(externalFile, "ext2"); } @Test public void testPosixFilePermissions() throws Exception { assertFileContents(standardFile, "std"); if (!Files.getFileStore(standardFile.toPath()).supportsFileAttributeView(PosixFileAttributeView.class)) { return; } PosixFileAttributeView posixStandardFileView = Files.getFileAttributeView(standardFile.toPath(), PosixFileAttributeView.class); assert posixStandardFileView != null; Set<PosixFilePermission> readWritePermissions = new HashSet<>(Arrays.asList(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, OTHERS_READ)); //Setting 761 on the file posixStandardFileView.setPermissions(readWritePermissions); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", standardFile.getCanonicalPath(), false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(standardFile.getCanonicalPath(), bootingFile.getCanonicalPath()); Path testPermissions = Files.createFile(standardDir.toPath().resolve("TestPermissions.tmp")); PosixFileAttributeView posixDefaultCreatedFilePermissionView = Files.getFileAttributeView(testPermissions, PosixFileAttributeView.class); assert posixDefaultCreatedFilePermissionView != null; Set<PosixFilePermission> defaultPermissions = posixDefaultCreatedFilePermissionView.readAttributes().permissions(); assertThat(defaultPermissions, hasItem(OWNER_READ)); assertThat(defaultPermissions, hasItem(OWNER_WRITE)); assertThat(defaultPermissions, not(hasItem(OWNER_EXECUTE))); Files.delete(testPermissions); configurationFile.successfulBoot(); Set<PosixFilePermission> configurationFilePemissions = posixStandardFileView.readAttributes().permissions(); assertThat(configurationFilePemissions, hasItem(OWNER_READ)); assertThat(configurationFilePemissions, hasItem(OWNER_WRITE)); assertThat(configurationFilePemissions, hasItem(OWNER_EXECUTE)); } @Test public void testAclFilePermissions() throws Exception { assertFileContents(standardFile, "std"); if (!Files.getFileStore(standardFile.toPath()).supportsFileAttributeView(AclFileAttributeView.class)) { return; } AclFileAttributeView aclStandardFileView = Files.getFileAttributeView(standardFile.toPath(), AclFileAttributeView.class); assert aclStandardFileView != null; List<AclEntry> aclEntries = aclStandardFileView.getAcl(); List<AclEntry> readWritePermissions = new ArrayList<>(aclEntries.size()); final UserPrincipal owner = aclStandardFileView.getOwner(); //Setting execute permissions on the file for(AclEntry entry : aclEntries) { if(entry.principal().equals(owner)) { readWritePermissions.add(createConfigurationAccessACLEntry(entry.principal())); } else { readWritePermissions.add(entry); } } aclStandardFileView.setAcl(readWritePermissions); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", standardFile.getCanonicalPath(), false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(standardFile.getCanonicalPath(), bootingFile.getCanonicalPath()); Path testPermissions = Files.createFile(standardDir.toPath().resolve("TestPermissions.tmp")); AclFileAttributeView aclDefaultCreatedFilePermissionView = Files.getFileAttributeView(testPermissions, AclFileAttributeView.class); assert aclDefaultCreatedFilePermissionView != null; List<AclEntry> defaultPermissions = aclDefaultCreatedFilePermissionView.getAcl(); Set<AclEntryPermission> ownerPermissions = getOwnerPermissions(defaultPermissions, aclDefaultCreatedFilePermissionView.getOwner()); if (!ownerPermissions.isEmpty()) { assertThat(ownerPermissions.toString(), ownerPermissions, hasItem(AclEntryPermission.WRITE_OWNER)); } Files.delete(testPermissions); configurationFile.successfulBoot(); List<AclEntry> configurationFilePermissions = aclStandardFileView.getAcl(); ownerPermissions = getOwnerPermissions(configurationFilePermissions, owner); assertThat(ownerPermissions.toString(), ownerPermissions, not(hasItem(AclEntryPermission.WRITE_OWNER))); } private AclEntry createConfigurationAccessACLEntry(UserPrincipal user) { AclEntry entry = AclEntry .newBuilder() .setType(AclEntryType.ALLOW) .setPrincipal(user) .setPermissions( AclEntryPermission.WRITE_NAMED_ATTRS, AclEntryPermission.WRITE_DATA, AclEntryPermission.WRITE_ATTRIBUTES, AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.APPEND_DATA, AclEntryPermission.READ_DATA, AclEntryPermission.READ_NAMED_ATTRS, AclEntryPermission.READ_ACL, AclEntryPermission.SYNCHRONIZE, AclEntryPermission.DELETE) .setFlags(AclEntryFlag.FILE_INHERIT) .build(); return entry; } private Set<AclEntryPermission> getOwnerPermissions(Collection<AclEntry> entries, UserPrincipal owner) { return entries.stream() .filter(aclEntry -> aclEntry.principal().equals(owner)) .map(AclEntry::permissions) .flatMap(Set::stream).collect(Collectors.toSet()); } @Test public void testNonPersistentReload() throws Exception { assertFileContents(standardFile, "std"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", standardFile.getCanonicalPath(), false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(standardFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); checkFiles(null, "std", "std", "std", "std"); store(persister, "One"); checkFiles(null, "std", "std", "std", "One", "std"); configurationFile.resetBootFile(false, null); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(standardFile.getCanonicalPath(), bootingFile.getCanonicalPath()); configurationFile.successfulBoot(); checkFiles(null, "std", "std", "std", "std"); store(persister, "One"); checkFiles(null, "std", "std", "std", "One", "std"); configurationFile.resetBootFile(true, null); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(addSuffix(standardFile, "last"), bootingFile.getCanonicalPath()); configurationFile.successfulBoot(); checkFiles(null, "std", "std", "One", "One"); } @Test public void testReloadPersistentSpecifyingNewConfig() throws Exception { assertFileContents(standardFile, "std"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", null, true); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(standardFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); store(persister, "One"); checkFiles(null, "One", "std", "std", "One", "std"); //Make sure that a reset to a snapshot loads that file configurationFile.snapshot(); ConfigurationPersister.SnapshotInfo snapshotInfo = configurationFile.listSnapshots(); Assert.assertEquals(1, snapshotInfo.names().size()); store(persister, "Two"); checkFiles(null, "Two", "std", "std", "Two", "std", "One"); configurationFile.resetBootFile(true, snapshotInfo.names().get(0)); bootingFile = configurationFile.getBootFile(); File snapshotFile = new File(snapshotInfo.getSnapshotDirectory(), snapshotInfo.names().get(0)); Assert.assertEquals(snapshotFile.getCanonicalFile(), bootingFile.getCanonicalFile()); configurationFile.successfulBoot(); checkFiles(null, "One", "std", "One", "One"); //Make sure that a reload to last loads that file store(persister, "Two"); checkFiles(null, "Two", "std", "One", "Two", "One"); configurationFile.resetBootFile(true, "last"); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(lastFile.getCanonicalFile(), bootingFile.getCanonicalFile()); configurationFile.successfulBoot(); checkFiles(null, "Two", "std", "Two", "Two"); //Make sure that a reload to initial loads that file store(persister, "Three"); checkFiles(null, "Three", "std", "Two", "Three", "Two"); configurationFile.resetBootFile(true, "initial"); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(initialFile.getCanonicalFile(), bootingFile.getCanonicalFile()); configurationFile.successfulBoot(); checkFiles(null, "std", "std", "std", "std"); } @Test public void testReloadNonPersistentSpecifyingNewConfig() throws Exception { assertFileContents(standardFile, "std"); ConfigurationFile configurationFile = new ConfigurationFile(standardDir, "standard.xml", null, false); File bootingFile = configurationFile.getBootFile(); Assert.assertEquals(standardFile.getCanonicalPath(), bootingFile.getCanonicalPath()); TestConfigurationFilePersister persister = new TestConfigurationFilePersister(configurationFile); configurationFile.successfulBoot(); checkDirectoryExists(historyDir); checkDirectoryExists(currentHistoryDir); store(persister, "One"); checkFiles(null, "std", "std", "std", "One", "std"); //Make sure that a reset to a snapshot loads that file configurationFile.snapshot(); ConfigurationPersister.SnapshotInfo snapshotInfo = configurationFile.listSnapshots(); Assert.assertEquals(1, snapshotInfo.names().size()); store(persister, "Two"); checkFiles(null, "std", "std", "std", "Two", "std", "One"); configurationFile.resetBootFile(true, snapshotInfo.names().get(0)); bootingFile = configurationFile.getBootFile(); File snapshotFile = new File(snapshotInfo.getSnapshotDirectory(), snapshotInfo.names().get(0)); Assert.assertEquals(snapshotFile.getCanonicalFile(), bootingFile.getCanonicalFile()); configurationFile.successfulBoot(); checkFiles(null, "std", "std", "One", "One"); //Make sure that a reload to last loads that file store(persister, "Two"); checkFiles(null, "std", "std", "One", "Two", "One"); configurationFile.resetBootFile(true, "last"); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(lastFile.getCanonicalFile(), bootingFile.getCanonicalFile()); configurationFile.successfulBoot(); checkFiles(null, "std", "std", "Two", "Two"); //Make sure that a reload to initial loads that file store(persister, "Three"); checkFiles(null, "std", "std", "Two", "Three", "Two"); configurationFile.resetBootFile(true, "initial"); bootingFile = configurationFile.getBootFile(); Assert.assertEquals(initialFile.getCanonicalFile(), bootingFile.getCanonicalFile()); configurationFile.successfulBoot(); checkFiles(null, "std", "std", "std", "std"); } private String addSuffix(File file, String suffix) throws IOException { StringBuilder builder = new StringBuilder(file.getParentFile().getCanonicalPath()); System.out.println(builder); builder.append(File.separatorChar); builder.append(file.getName().replace('.', '_') + "_history" + File.separatorChar); builder.append(file.getName().substring(0, file.getName().lastIndexOf(".xml"))); builder.append("."); builder.append(suffix); builder.append(".xml"); System.out.println(builder.toString()); return builder.toString(); } private void checkFiles(String mainFileName, String main, String initial, String boot, String last, String... versions) throws Exception { File mainFile = this.standardFile; File bootFile = this.bootFile; File lastFile = this.lastFile; File initialFile = this.initialFile; if (mainFileName != null) { mainFile = new File(mainFile.getAbsoluteFile().getParent(), mainFileName + ".xml"); bootFile = new File(bootFile.getAbsoluteFile().getParent(), mainFileName + ".boot.xml"); lastFile = new File(bootFile.getAbsoluteFile().getParent(), mainFileName + ".last.xml"); initialFile = new File(bootFile.getAbsoluteFile().getParent(), mainFileName + ".initial.xml"); } assertFileContents(mainFile, main); assertFileContents(bootFile, boot); assertFileContents(lastFile, last); assertFileContents(initialFile, initial); checkVersionedHistory(mainFileName == null ? "standard" : mainFileName, versions); } private void store(TestConfigurationPersister persister, String s) throws Exception { persister.store(new ModelNode(s), Collections.<PathAddress>emptySet()).commit(); } private File createDir(File dir, String name) { checkDirectoryExists(dir); File created = new File(dir, name); created.mkdir(); if (!created.exists()) { Assert.fail("Could not create " + created); } return created; } private File createFile(File dir, String name, String contents) throws IOException { checkDirectoryExists(dir); File file = new File(dir, name); if (contents != null) { Files.write(file.toPath(), contents.getBytes(StandardCharsets.UTF_8)); } return file; } private void checkDirectoryExists(File dir) { Assert.assertTrue(dir + " does not exist", dir.exists()); Assert.assertTrue(dir + " is not a directory", dir.isDirectory()); } private void delete(File file) { if (file.isDirectory()) { for (String name : file.list()) { delete(new File(file, name)); } } if (!file.delete() && file.exists()) { Assert.fail("Could not delete " + file); } } private void assertFileContents(File file, String expectedContents) throws Exception { Assert.assertTrue(file + " does not exist", file.exists()); StringBuilder sb = new StringBuilder(); try (BufferedReader in = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)){ String s = in.readLine(); while (s != null) { sb.append(s); s = in.readLine(); } } Assert.assertEquals(expectedContents, sb.toString()); } private void checkVersionedHistory(String name, String... versions) throws Exception { for (int i = 0; i <= versions.length; i++) { File file = new File(currentHistoryDir, name + ".v" + (i + 1) + ".xml"); if (i == versions.length) { Assert.assertFalse(file.exists()); } else { assertFileContents(file, versions[i]); } } } private class TestFileResourcePersister extends TestConfigurationPersister { private final File fileName; public TestFileResourcePersister(File fileName) { this.fileName = fileName; } @Override public PersistenceResource create(ModelNode model) throws ConfigurationPersistenceException { return new FilePersistenceResource(model, fileName, this); } } private class TestConfigurationFilePersister extends TestConfigurationPersister { private final ConfigurationFile configurationFile; public TestConfigurationFilePersister(ConfigurationFile configurationFile) { this.configurationFile = configurationFile; } @Override PersistenceResource create(ModelNode model) throws ConfigurationPersistenceException { return new ConfigurationFilePersistenceResource(model, configurationFile, this); } } }