mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-17 18:51:10 +01:00
Handle resources, never left left opened file handler on windows (#1857)
On windows unit tests are failing because junit checks if all @tempdir directries are empty and can be deleted after test run. But due to opened file handles (not closed resource streams) Windows keeps files, which are "in use". Linux is less strict in this area. Additionally I want highlight that XMLStreamReaderImpl/XMLStreamWriterImpl from apache.xerces library (in OpenJDK11 at least) which are picked at runtime as xml parser implementation - they don't close associated resources. BTW, I thing that relying on some runtime (sometimes - unpredictable) dependencies - is bad practice, but this it up to separate topic. Additional fix: in IOUtil is file is locked (due to permissions or opened handle) - it will undlessly try-and-retry to delete it until end of the world, on windows.
This commit is contained in:
@@ -391,9 +391,7 @@ public final class IOUtil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 20; !file.delete(); i--)
|
for (int i = 20; !file.delete() && i > 0; i--)
|
||||||
{
|
|
||||||
if (i <= 20)
|
|
||||||
{
|
{
|
||||||
String message = "could not delete file ".concat(file.getPath());
|
String message = "could not delete file ".concat(file.getPath());
|
||||||
|
|
||||||
@@ -405,7 +403,6 @@ public final class IOUtil
|
|||||||
{
|
{
|
||||||
throw new IOException(message);
|
throw new IOException(message);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import com.google.common.collect.ImmutableMap;
|
|||||||
import org.junit.jupiter.api.Nested;
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@@ -38,19 +40,19 @@ class BaseDirectoryTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldGetFromClassPathResource() {
|
void shouldGetFromClassPathResource() {
|
||||||
BaseDirectory directory = builder().withClassPathResource("/sonia/scm/basedirectory.properties").create();
|
BaseDirectory directory = builder().withClassPathResource("/sonia/scm/basedirectory.properties").create();
|
||||||
assertThat(directory.find().toString()).isEqualTo("/tmp/scm_home");
|
assertThat(directory.find()).isEqualTo(Paths.get("/tmp/scm_home"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldGetFromSystemProperty() {
|
void shouldGetFromSystemProperty() {
|
||||||
BaseDirectory directory = builder().withSystemProperty(BaseDirectory.SYSTEM_PROPERTY, "/tmp/scm_home").create();
|
BaseDirectory directory = builder().withSystemProperty(BaseDirectory.SYSTEM_PROPERTY, "/tmp/scm_home").create();
|
||||||
assertThat(directory.find().toString()).isEqualTo("/tmp/scm_home");
|
assertThat(directory.find()).isEqualTo(Paths.get("/tmp/scm_home"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldGetFromEnvironmentVariable() {
|
void shouldGetFromEnvironmentVariable() {
|
||||||
BaseDirectory directory = builder().withEnvironment(BaseDirectory.ENVIRONMENT_VARIABLE, "/tmp/scm_home").create();
|
BaseDirectory directory = builder().withEnvironment(BaseDirectory.ENVIRONMENT_VARIABLE, "/tmp/scm_home").create();
|
||||||
assertThat(directory.find().toString()).isEqualTo("/tmp/scm_home");
|
assertThat(directory.find()).isEqualTo(Paths.get("/tmp/scm_home"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@@ -59,19 +61,19 @@ class BaseDirectoryTest {
|
|||||||
@Test
|
@Test
|
||||||
void linux() {
|
void linux() {
|
||||||
BaseDirectory directory = builder().withSystemProperty("user.home", "/tmp").create();
|
BaseDirectory directory = builder().withSystemProperty("user.home", "/tmp").create();
|
||||||
assertThat(directory.find().toString()).isEqualTo("/tmp/.scm");
|
assertThat(directory.find()).isEqualTo(Paths.get("/tmp/.scm"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void osx() {
|
void osx() {
|
||||||
BaseDirectory directory = builder().withOsx().withSystemProperty("user.home", "/tmp").create();
|
BaseDirectory directory = builder().withOsx().withSystemProperty("user.home", "/tmp").create();
|
||||||
assertThat(directory.find().toString()).isEqualTo("/tmp/Library/Application Support/SCM-Manager");
|
assertThat(directory.find()).isEqualTo(Paths.get("/tmp/Library/Application Support/SCM-Manager"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void windows() {
|
void windows() {
|
||||||
BaseDirectory directory = builder().withWindows().withEnvironment("APPDATA", "/tmp").create();
|
BaseDirectory directory = builder().withWindows().withEnvironment("APPDATA", "/tmp").create();
|
||||||
assertThat(directory.find().toString()).isEqualTo("/tmp\\SCM-Manager");
|
assertThat(directory.find()).isEqualTo(Paths.get("/tmp\\SCM-Manager"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
@@ -137,17 +138,14 @@ class SmpArchiveTest {
|
|||||||
return archiveFile;
|
return archiveFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private XMLStreamWriter createStreamWriter(File file) throws IOException, XMLStreamException {
|
|
||||||
return XMLOutputFactory.newFactory().createXMLStreamWriter(new FileOutputStream(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeDescriptor(File descriptor, String name, String version) throws IOException, XMLStreamException {
|
private void writeDescriptor(File descriptor, String name, String version) throws IOException, XMLStreamException {
|
||||||
IOUtil.mkdirs(descriptor.getParentFile());
|
IOUtil.mkdirs(descriptor.getParentFile());
|
||||||
|
|
||||||
XMLStreamWriter writer = null;
|
XMLStreamWriter writer = null;
|
||||||
|
|
||||||
try {
|
try (OutputStream os = new FileOutputStream(descriptor)) {
|
||||||
writer = createStreamWriter(descriptor);
|
writer = XMLOutputFactory.newFactory().createXMLStreamWriter(os);
|
||||||
|
|
||||||
writer.writeStartDocument();
|
writer.writeStartDocument();
|
||||||
writer.writeStartElement("plugin");
|
writer.writeStartElement("plugin");
|
||||||
writer.writeStartElement("information");
|
writer.writeStartElement("information");
|
||||||
@@ -157,12 +155,9 @@ class SmpArchiveTest {
|
|||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
writer.writeEndDocument();
|
writer.writeEndDocument();
|
||||||
} finally {
|
|
||||||
if (writer != null) {
|
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void writeElement(XMLStreamWriter writer, String name, String value) throws XMLStreamException {
|
private void writeElement(XMLStreamWriter writer, String name, String value) throws XMLStreamException {
|
||||||
if (!Strings.isNullOrEmpty(value)) {
|
if (!Strings.isNullOrEmpty(value)) {
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ import javax.xml.stream.XMLStreamException;
|
|||||||
import javax.xml.stream.XMLStreamReader;
|
import javax.xml.stream.XMLStreamReader;
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
import javax.xml.stream.XMLStreamWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -67,7 +70,8 @@ class PathDatabase {
|
|||||||
|
|
||||||
CopyOnWrite.withTemporaryFile(
|
CopyOnWrite.withTemporaryFile(
|
||||||
temp -> {
|
temp -> {
|
||||||
try (IndentXMLStreamWriter writer = XmlStreams.createWriter(temp)) {
|
try (Writer ioWriter = Files.newBufferedWriter(temp, StandardCharsets.UTF_8)) {
|
||||||
|
try (IndentXMLStreamWriter writer = XmlStreams.createWriter(ioWriter)) {
|
||||||
writer.writeStartDocument(ENCODING, VERSION);
|
writer.writeStartDocument(ENCODING, VERSION);
|
||||||
|
|
||||||
writeRepositoriesStart(writer, creationTime, lastModified);
|
writeRepositoriesStart(writer, creationTime, lastModified);
|
||||||
@@ -77,13 +81,14 @@ class PathDatabase {
|
|||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
|
||||||
writer.writeEndDocument();
|
writer.writeEndDocument();
|
||||||
} catch (XMLStreamException | IOException ex) {
|
} catch (XMLStreamException ex) {
|
||||||
throw new InternalRepositoryException(
|
throw new InternalRepositoryException(
|
||||||
ContextEntry.ContextBuilder.entity(Path.class, storePath.toString()).build(),
|
ContextEntry.ContextBuilder.entity(Path.class, storePath.toString()).build(),
|
||||||
"failed to write repository path database",
|
"failed to write repository path database",
|
||||||
ex
|
ex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
storePath
|
storePath
|
||||||
);
|
);
|
||||||
@@ -121,8 +126,8 @@ class PathDatabase {
|
|||||||
void read(OnRepositories onRepositories, OnRepository onRepository) {
|
void read(OnRepositories onRepositories, OnRepository onRepository) {
|
||||||
LOG.trace("read repository path database from {}", storePath);
|
LOG.trace("read repository path database from {}", storePath);
|
||||||
XMLStreamReader reader = null;
|
XMLStreamReader reader = null;
|
||||||
try {
|
try (Reader inputReader = Files.newBufferedReader(storePath, StandardCharsets.UTF_8)) {
|
||||||
reader = XmlStreams.createReader(storePath);
|
reader = XmlStreams.createReader(inputReader);
|
||||||
|
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
int eventType = reader.next();
|
int eventType = reader.next();
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import javax.inject.Inject;
|
|||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import javax.xml.stream.XMLStreamReader;
|
import javax.xml.stream.XMLStreamReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -135,8 +137,8 @@ public class FileStoreExporter implements StoreExporter {
|
|||||||
|
|
||||||
private StoreType determineConfigType(Path storePath) {
|
private StoreType determineConfigType(Path storePath) {
|
||||||
XMLStreamReader reader = null;
|
XMLStreamReader reader = null;
|
||||||
try {
|
try (Reader inputReader = Files.newBufferedReader(storePath, StandardCharsets.UTF_8)) {
|
||||||
reader = XmlStreams.createReader(storePath);
|
reader = XmlStreams.createReader(inputReader);
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
if (
|
if (
|
||||||
"configuration".equals(reader.getLocalName())
|
"configuration".equals(reader.getLocalName())
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ import javax.xml.bind.Marshaller;
|
|||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
import javax.xml.stream.XMLStreamReader;
|
import javax.xml.stream.XMLStreamReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -138,8 +142,9 @@ public class JAXBConfigurationEntryStore<V> implements ConfigurationEntryStore<V
|
|||||||
|
|
||||||
context.withUnmarshaller(u -> {
|
context.withUnmarshaller(u -> {
|
||||||
XMLStreamReader reader = null;
|
XMLStreamReader reader = null;
|
||||||
try {
|
|
||||||
reader = XmlStreams.createReader(file);
|
try (Reader inputReader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
|
||||||
|
reader = XmlStreams.createReader(inputReader);
|
||||||
|
|
||||||
// configuration
|
// configuration
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
@@ -190,7 +195,8 @@ public class JAXBConfigurationEntryStore<V> implements ConfigurationEntryStore<V
|
|||||||
|
|
||||||
CopyOnWrite.withTemporaryFile(
|
CopyOnWrite.withTemporaryFile(
|
||||||
temp -> {
|
temp -> {
|
||||||
try (IndentXMLStreamWriter writer = XmlStreams.createWriter(temp)) {
|
try (Writer ioWriter = Files.newBufferedWriter(temp, StandardCharsets.UTF_8);
|
||||||
|
IndentXMLStreamWriter writer = XmlStreams.createWriter(ioWriter)) {
|
||||||
writer.writeStartDocument();
|
writer.writeStartDocument();
|
||||||
|
|
||||||
// configuration start
|
// configuration start
|
||||||
|
|||||||
@@ -32,13 +32,8 @@ import javax.xml.stream.XMLOutputFactory;
|
|||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import javax.xml.stream.XMLStreamReader;
|
import javax.xml.stream.XMLStreamReader;
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
import javax.xml.stream.XMLStreamWriter;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
public final class XmlStreams {
|
public final class XmlStreams {
|
||||||
|
|
||||||
@@ -67,31 +62,13 @@ public final class XmlStreams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XMLStreamReader createReader(Path path) throws IOException, XMLStreamException {
|
public static XMLStreamReader createReader(Reader reader) throws XMLStreamException {
|
||||||
return createReader(Files.newBufferedReader(path, StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static XMLStreamReader createReader(File file) throws IOException, XMLStreamException {
|
|
||||||
return createReader(file.toPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static XMLStreamReader createReader(Reader reader) throws XMLStreamException {
|
|
||||||
XMLInputFactory factory = XMLInputFactory.newInstance();
|
XMLInputFactory factory = XMLInputFactory.newInstance();
|
||||||
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
|
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
|
||||||
return factory.createXMLStreamReader(reader);
|
return factory.createXMLStreamReader(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IndentXMLStreamWriter createWriter(Writer writer) throws XMLStreamException {
|
||||||
public static IndentXMLStreamWriter createWriter(Path path) throws IOException, XMLStreamException {
|
|
||||||
return createWriter(Files.newBufferedWriter(path, StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IndentXMLStreamWriter createWriter(File file) throws IOException, XMLStreamException {
|
|
||||||
return createWriter(file.toPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IndentXMLStreamWriter createWriter(Writer writer) throws XMLStreamException {
|
|
||||||
return new IndentXMLStreamWriter(XMLOutputFactory.newFactory().createXMLStreamWriter(writer));
|
return new IndentXMLStreamWriter(XMLOutputFactory.newFactory().createXMLStreamWriter(writer));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.io.TempDir;
|
|||||||
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -43,9 +44,11 @@ class CopyOnWriteTest {
|
|||||||
void shouldCreateNewFile(@TempDir Path tempDir) {
|
void shouldCreateNewFile(@TempDir Path tempDir) {
|
||||||
Path expectedFile = tempDir.resolve("toBeCreated.txt");
|
Path expectedFile = tempDir.resolve("toBeCreated.txt");
|
||||||
|
|
||||||
withTemporaryFile(
|
withTemporaryFile(file -> {
|
||||||
file -> new FileOutputStream(file.toFile()).write("great success".getBytes()),
|
try (OutputStream os = new FileOutputStream(file.toFile())) {
|
||||||
expectedFile);
|
os.write("great success".getBytes());
|
||||||
|
}
|
||||||
|
}, expectedFile);
|
||||||
|
|
||||||
Assertions.assertThat(expectedFile).hasContent("great success");
|
Assertions.assertThat(expectedFile).hasContent("great success");
|
||||||
}
|
}
|
||||||
@@ -55,34 +58,40 @@ class CopyOnWriteTest {
|
|||||||
Path expectedFile = tempDir.resolve("toBeOverwritten.txt");
|
Path expectedFile = tempDir.resolve("toBeOverwritten.txt");
|
||||||
Files.createFile(expectedFile);
|
Files.createFile(expectedFile);
|
||||||
|
|
||||||
withTemporaryFile(
|
withTemporaryFile(file -> {
|
||||||
file -> new FileOutputStream(file.toFile()).write("great success".getBytes()),
|
try (OutputStream os = new FileOutputStream(file.toFile())) {
|
||||||
expectedFile);
|
os.write("great success".getBytes());
|
||||||
|
}
|
||||||
|
}, expectedFile);
|
||||||
|
|
||||||
Assertions.assertThat(expectedFile).hasContent("great success");
|
Assertions.assertThat(expectedFile).hasContent("great success");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFailForDirectory(@TempDir Path tempDir) {
|
void shouldFailForDirectory(@TempDir Path tempDir) {
|
||||||
assertThrows(IllegalArgumentException.class,
|
assertThrows(IllegalArgumentException.class, () -> withTemporaryFile(file -> {
|
||||||
() -> withTemporaryFile(
|
try (OutputStream os = new FileOutputStream(file.toFile())) {
|
||||||
file -> new FileOutputStream(file.toFile()).write("should not be written".getBytes()),
|
os.write("should not be written".getBytes());
|
||||||
tempDir));
|
}
|
||||||
|
}, tempDir));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFailForMissingDirectory() {
|
void shouldFailForMissingDirectory() {
|
||||||
assertThrows(
|
assertThrows(IllegalArgumentException.class, () -> withTemporaryFile(file -> {
|
||||||
IllegalArgumentException.class,
|
try (OutputStream os = new FileOutputStream(file.toFile())) {
|
||||||
() -> withTemporaryFile(
|
os.write("should not be written".getBytes());
|
||||||
file -> new FileOutputStream(file.toFile()).write("should not be written".getBytes()),
|
}
|
||||||
Paths.get("someFile")));
|
}, Paths.get("someFile")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldKeepBackupIfTemporaryFileCouldNotBeWritten(@TempDir Path tempDir) throws IOException {
|
void shouldKeepBackupIfTemporaryFileCouldNotBeWritten(@TempDir Path tempDir) throws IOException {
|
||||||
Path unchangedOriginalFile = tempDir.resolve("notToBeDeleted.txt");
|
Path unchangedOriginalFile = tempDir.resolve("notToBeDeleted.txt");
|
||||||
new FileOutputStream(unchangedOriginalFile.toFile()).write("this should be kept".getBytes());
|
|
||||||
|
try (OutputStream unchangedOriginalOs = new FileOutputStream(unchangedOriginalFile.toFile())) {
|
||||||
|
unchangedOriginalOs.write("this should be kept".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
StoreException.class,
|
StoreException.class,
|
||||||
@@ -111,7 +120,10 @@ class CopyOnWriteTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldKeepBackupIfTemporaryFileIsMissing(@TempDir Path tempDir) throws IOException {
|
void shouldKeepBackupIfTemporaryFileIsMissing(@TempDir Path tempDir) throws IOException {
|
||||||
Path backedUpFile = tempDir.resolve("notToBeDeleted.txt");
|
Path backedUpFile = tempDir.resolve("notToBeDeleted.txt");
|
||||||
new FileOutputStream(backedUpFile.toFile()).write("this should be kept".getBytes());
|
|
||||||
|
try (OutputStream backedUpOs = new FileOutputStream(backedUpFile.toFile())) {
|
||||||
|
backedUpOs.write("this should be kept".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
StoreException.class,
|
StoreException.class,
|
||||||
@@ -125,11 +137,16 @@ class CopyOnWriteTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldDeleteExistingFile(@TempDir Path tempDir) throws IOException {
|
void shouldDeleteExistingFile(@TempDir Path tempDir) throws IOException {
|
||||||
Path expectedFile = tempDir.resolve("toBeReplaced.txt");
|
Path expectedFile = tempDir.resolve("toBeReplaced.txt");
|
||||||
new FileOutputStream(expectedFile.toFile()).write("this should be removed".getBytes());
|
|
||||||
|
|
||||||
withTemporaryFile(
|
try (OutputStream expectedOs = new FileOutputStream(expectedFile.toFile())) {
|
||||||
file -> new FileOutputStream(file.toFile()).write("overwritten".getBytes()),
|
expectedOs.write("this should be removed".getBytes());
|
||||||
expectedFile);
|
}
|
||||||
|
|
||||||
|
withTemporaryFile(file -> {
|
||||||
|
try (OutputStream os = new FileOutputStream(file.toFile())) {
|
||||||
|
os.write("overwritten".getBytes()) ;
|
||||||
|
}
|
||||||
|
}, expectedFile);
|
||||||
|
|
||||||
Assertions.assertThat(Files.list(tempDir)).hasSize(1);
|
Assertions.assertThat(Files.list(tempDir)).hasSize(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ class RepositoryImportStep implements ImportStep {
|
|||||||
private void importFromTemporaryPath(ImportState state, Path path) {
|
private void importFromTemporaryPath(ImportState state, Path path) {
|
||||||
LOG.debug("Importing repository from temporary location in work dir");
|
LOG.debug("Importing repository from temporary location in work dir");
|
||||||
state.getLogger().step("importing repository from temporary location");
|
state.getLogger().step("importing repository from temporary location");
|
||||||
try {
|
try (InputStream is = Files.newInputStream(path)) {
|
||||||
unbundleRepository(state, Files.newInputStream(path));
|
unbundleRepository(state, is);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ImportFailedException(
|
throw new ImportFailedException(
|
||||||
entity(state.getRepository()).build(),
|
entity(state.getRepository()).build(),
|
||||||
|
|||||||
@@ -34,17 +34,19 @@ import sonia.scm.version.Version;
|
|||||||
import sonia.scm.xml.XmlStreams;
|
import sonia.scm.xml.XmlStreams;
|
||||||
|
|
||||||
import javax.xml.XMLConstants;
|
import javax.xml.XMLConstants;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import javax.xml.stream.XMLStreamReader;
|
import javax.xml.stream.XMLStreamReader;
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
import javax.xml.transform.TransformerFactory;
|
import javax.xml.transform.TransformerFactory;
|
||||||
import javax.xml.transform.dom.DOMSource;
|
import javax.xml.transform.dom.DOMSource;
|
||||||
import javax.xml.transform.stream.StreamResult;
|
import javax.xml.transform.stream.StreamResult;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -74,8 +76,8 @@ abstract class DifferentiateBetweenConfigAndConfigEntryUpdateStep {
|
|||||||
private boolean isConfigEntryFile(Path potentialFile) {
|
private boolean isConfigEntryFile(Path potentialFile) {
|
||||||
LOG.trace("Testing whether file is config entry file without mark: {}", potentialFile);
|
LOG.trace("Testing whether file is config entry file without mark: {}", potentialFile);
|
||||||
XMLStreamReader reader = null;
|
XMLStreamReader reader = null;
|
||||||
try {
|
try (Reader inputReader = Files.newBufferedReader(potentialFile, StandardCharsets.UTF_8)) {
|
||||||
reader = XmlStreams.createReader(potentialFile);
|
reader = XmlStreams.createReader(inputReader);
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
if ("configuration".equals(reader.getLocalName())) {
|
if ("configuration".equals(reader.getLocalName())) {
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
@@ -104,26 +106,25 @@ abstract class DifferentiateBetweenConfigAndConfigEntryUpdateStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeXmlDocument(Document configEntryDocument, Path temporaryFile) throws TransformerException {
|
private void writeXmlDocument(Document configEntryDocument, Path temporaryFile) throws TransformerException {
|
||||||
try {
|
try (OutputStream os = Files.newOutputStream(temporaryFile)) {
|
||||||
TransformerFactory factory = TransformerFactory.newInstance();
|
final TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
||||||
Transformer transformer = factory.newTransformer();
|
final DOMSource domSource = new DOMSource(configEntryDocument);
|
||||||
DOMSource domSource = new DOMSource(configEntryDocument);
|
|
||||||
StreamResult streamResult = new StreamResult(Files.newOutputStream(temporaryFile));
|
factory.newTransformer().transform(domSource, new StreamResult(os));
|
||||||
transformer.transform(domSource, streamResult);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UpdateException("Could not write modified config entry file", e);
|
throw new UpdateException("Could not write modified config entry file", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Document readAsXmlDocument(Path configFile) {
|
private Document readAsXmlDocument(Path configFile) {
|
||||||
try {
|
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
|
||||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
|
||||||
return builder.parse(Files.newInputStream(configFile));
|
try (InputStream is = Files.newInputStream(configFile)) {
|
||||||
|
return factory.newDocumentBuilder().parse(is);
|
||||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||||
throw new UpdateException("Could not read config entry file", e);
|
throw new UpdateException("Could not read config entry file", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,14 +91,8 @@ class CopyMigrationStrategyTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertDirectoriesEqual(Path targetDataDir, Path originalDataDir) {
|
private void assertDirectoriesEqual(Path targetDataDir, Path originalDataDir) {
|
||||||
Stream<Path> list = null;
|
try (Stream<Path> list = Files.list(originalDataDir)) {
|
||||||
try {
|
list.forEach(original -> {
|
||||||
list = Files.list(originalDataDir);
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail("could not read original directory", e);
|
|
||||||
}
|
|
||||||
list.forEach(
|
|
||||||
original -> {
|
|
||||||
Path expectedTarget = targetDataDir.resolve(original.getFileName());
|
Path expectedTarget = targetDataDir.resolve(original.getFileName());
|
||||||
assertThat(expectedTarget).exists();
|
assertThat(expectedTarget).exists();
|
||||||
if (Files.isDirectory(original)) {
|
if (Files.isDirectory(original)) {
|
||||||
@@ -106,7 +100,9 @@ class CopyMigrationStrategyTest {
|
|||||||
} else {
|
} else {
|
||||||
assertThat(expectedTarget).hasSameContentAs(original);
|
assertThat(expectedTarget).hasSameContentAs(original);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
} catch (IOException e) {
|
||||||
|
fail("could not read original directory", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -43,16 +45,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
class DifferentiateBetweenConfigAndConfigEntryUpdateStepTest {
|
class DifferentiateBetweenConfigAndConfigEntryUpdateStepTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldNotModifyConfigFile(@TempDir Path temp) throws IOException {
|
void shouldNotModifyConfigFile(@TempDir Path temp) throws IOException, URISyntaxException {
|
||||||
Path configFile = temp.resolve("some.store.xml");
|
Path configFile = temp.resolve("some.store.xml");
|
||||||
copy(
|
|
||||||
getResource("sonia/scm/update/store/config_file.xml.content"),
|
try (OutputStream os = newOutputStream(configFile)) {
|
||||||
newOutputStream(configFile));
|
copy(getResource("sonia/scm/update/store/config_file.xml.content"), os);
|
||||||
|
|
||||||
new DifferentiateBetweenConfigAndConfigEntryUpdateStep() {}.updateAllInDirectory(temp);
|
new DifferentiateBetweenConfigAndConfigEntryUpdateStep() {}.updateAllInDirectory(temp);
|
||||||
|
|
||||||
assertContent(configFile, "sonia/scm/update/store/config_file.xml.content");
|
assertContent(configFile, "sonia/scm/update/store/config_file.xml.content");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldNotModifySingleLineFile(@TempDir Path temp) throws IOException {
|
void shouldNotModifySingleLineFile(@TempDir Path temp) throws IOException {
|
||||||
@@ -77,33 +80,35 @@ class DifferentiateBetweenConfigAndConfigEntryUpdateStepTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldIgnoreFilesWithoutXmlSuffix(@TempDir Path temp) throws IOException {
|
void shouldIgnoreFilesWithoutXmlSuffix(@TempDir Path temp) throws IOException, URISyntaxException {
|
||||||
Path otherFile = temp.resolve("some.other.file");
|
Path otherFile = temp.resolve("some.other.file");
|
||||||
copy(
|
|
||||||
getResource("sonia/scm/update/store/config_entry_file_without_mark.xml.content"),
|
try (OutputStream os = newOutputStream(otherFile)) {
|
||||||
newOutputStream(otherFile));
|
copy(getResource("sonia/scm/update/store/config_entry_file_without_mark.xml.content"), os);
|
||||||
|
|
||||||
new DifferentiateBetweenConfigAndConfigEntryUpdateStep() {}.updateAllInDirectory(temp);
|
new DifferentiateBetweenConfigAndConfigEntryUpdateStep() {}.updateAllInDirectory(temp);
|
||||||
|
|
||||||
assertContent(otherFile, "sonia/scm/update/store/config_entry_file_without_mark.xml.content");
|
assertContent(otherFile, "sonia/scm/update/store/config_entry_file_without_mark.xml.content");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleConfigEntryFile(@TempDir Path temp) throws IOException {
|
void shouldHandleConfigEntryFile(@TempDir Path temp) throws IOException, URISyntaxException {
|
||||||
Path configFile = temp.resolve("some.store.xml");
|
Path configFile = temp.resolve("some.store.xml");
|
||||||
copy(
|
|
||||||
getResource("sonia/scm/update/store/config_entry_file_without_mark.xml.content"),
|
try (OutputStream os = newOutputStream(configFile)) {
|
||||||
newOutputStream(configFile));
|
copy(getResource("sonia/scm/update/store/config_entry_file_without_mark.xml.content"), os);
|
||||||
|
|
||||||
new DifferentiateBetweenConfigAndConfigEntryUpdateStep() {}.updateAllInDirectory(temp);
|
new DifferentiateBetweenConfigAndConfigEntryUpdateStep() {}.updateAllInDirectory(temp);
|
||||||
|
|
||||||
assertThat(Files.readAllLines(configFile))
|
assertThat(Files.readAllLines(configFile))
|
||||||
.areAtLeastOne(new Condition<>(line -> line.contains("<configuration type=\"config-entry\">"), "line containing start tag with attribute"))
|
.areAtLeastOne(new Condition<>(line -> line.contains("<configuration type=\"config-entry\">"), "line containing start tag with attribute"))
|
||||||
.endsWith(Files.readAllLines(Paths.get(getResource("sonia/scm/update/store/config_entry_file.xml.content").getFile())).toArray(new String[9]));
|
.endsWith(Files.readAllLines(Paths.get(getResource("sonia/scm/update/store/config_entry_file.xml.content").toURI())).toArray(new String[9]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertContent(Path configFile, String expectedContentResource) {
|
private void assertContent(Path configFile, String expectedContentResource) throws URISyntaxException {
|
||||||
assertThat(configFile)
|
assertThat(configFile)
|
||||||
.hasSameTextualContentAs(Paths.get(getResource(expectedContentResource).getFile()));
|
.hasSameTextualContentAs(Paths.get(getResource(expectedContentResource).toURI()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user