mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-17 02:31:14 +01:00
Autocloseable streams in XML DB (#1868)
Introduce autocloseable streams for file handling in xml database module.
This commit is contained in:
4
gradle/changelog/windows_stream_handling.yaml
Normal file
4
gradle/changelog/windows_stream_handling.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- type: fixed
|
||||||
|
description: Closing of file streams ([#1857](https://github.com/scm-manager/scm-manager/pull/1857) and [#1868](https://github.com/scm-manager/scm-manager/pull/1868))
|
||||||
|
- type: fixed
|
||||||
|
description: Exit of retry loop for deletion of files ([#1857](https://github.com/scm-manager/scm-manager/pull/1857) and [#1868](https://github.com/scm-manager/scm-manager/pull/1868))
|
||||||
@@ -28,7 +28,6 @@ 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.nio.file.Paths;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sonia.scm.repository.xml;
|
package sonia.scm.repository.xml;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -29,16 +29,15 @@ import org.slf4j.LoggerFactory;
|
|||||||
import sonia.scm.ContextEntry;
|
import sonia.scm.ContextEntry;
|
||||||
import sonia.scm.repository.InternalRepositoryException;
|
import sonia.scm.repository.InternalRepositoryException;
|
||||||
import sonia.scm.store.CopyOnWrite;
|
import sonia.scm.store.CopyOnWrite;
|
||||||
import sonia.scm.xml.IndentXMLStreamWriter;
|
|
||||||
import sonia.scm.xml.XmlStreams;
|
import sonia.scm.xml.XmlStreams;
|
||||||
|
import sonia.scm.xml.XmlStreams.AutoCloseableXMLReader;
|
||||||
|
import sonia.scm.xml.XmlStreams.AutoCloseableXMLWriter;
|
||||||
|
|
||||||
|
import javax.xml.stream.XMLStreamConstants;
|
||||||
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.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;
|
||||||
@@ -70,24 +69,22 @@ class PathDatabase {
|
|||||||
|
|
||||||
CopyOnWrite.withTemporaryFile(
|
CopyOnWrite.withTemporaryFile(
|
||||||
temp -> {
|
temp -> {
|
||||||
try (Writer ioWriter = Files.newBufferedWriter(temp, StandardCharsets.UTF_8)) {
|
try (AutoCloseableXMLWriter writer = XmlStreams.createWriter(temp)) {
|
||||||
try (IndentXMLStreamWriter writer = XmlStreams.createWriter(ioWriter)) {
|
writer.writeStartDocument(ENCODING, VERSION);
|
||||||
writer.writeStartDocument(ENCODING, VERSION);
|
|
||||||
|
|
||||||
writeRepositoriesStart(writer, creationTime, lastModified);
|
writeRepositoriesStart(writer, creationTime, lastModified);
|
||||||
for (Map.Entry<String, Path> e : pathDatabase.entrySet()) {
|
for (Map.Entry<String, Path> e : pathDatabase.entrySet()) {
|
||||||
writeRepository(writer, e.getKey(), e.getValue());
|
writeRepository(writer, e.getKey(), e.getValue());
|
||||||
}
|
|
||||||
writer.writeEndElement();
|
|
||||||
|
|
||||||
writer.writeEndDocument();
|
|
||||||
} catch (XMLStreamException ex) {
|
|
||||||
throw new InternalRepositoryException(
|
|
||||||
ContextEntry.ContextBuilder.entity(Path.class, storePath.toString()).build(),
|
|
||||||
"failed to write repository path database",
|
|
||||||
ex
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
writer.writeEndElement();
|
||||||
|
|
||||||
|
writer.writeEndDocument();
|
||||||
|
} catch (XMLStreamException | IOException ex) {
|
||||||
|
throw new InternalRepositoryException(
|
||||||
|
ContextEntry.ContextBuilder.entity(Path.class, storePath.toString()).build(),
|
||||||
|
"failed to write repository path database",
|
||||||
|
ex
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
storePath
|
storePath
|
||||||
@@ -125,14 +122,12 @@ 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;
|
try (AutoCloseableXMLReader reader = XmlStreams.createReader(storePath)) {
|
||||||
try (Reader inputReader = Files.newBufferedReader(storePath, StandardCharsets.UTF_8)) {
|
|
||||||
reader = XmlStreams.createReader(inputReader);
|
|
||||||
|
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
int eventType = reader.next();
|
int eventType = reader.next();
|
||||||
|
|
||||||
if (eventType == XMLStreamReader.START_ELEMENT) {
|
if (eventType == XMLStreamConstants.START_ELEMENT) {
|
||||||
String element = reader.getLocalName();
|
String element = reader.getLocalName();
|
||||||
if (ELEMENT_REPOSITORIES.equals(element)) {
|
if (ELEMENT_REPOSITORIES.equals(element)) {
|
||||||
readRepositories(reader, onRepositories);
|
readRepositories(reader, onRepositories);
|
||||||
@@ -147,8 +142,6 @@ class PathDatabase {
|
|||||||
"failed to read repository path database",
|
"failed to read repository path database",
|
||||||
ex
|
ex
|
||||||
);
|
);
|
||||||
} finally {
|
|
||||||
XmlStreams.close(reader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,13 +30,11 @@ import sonia.scm.repository.Repository;
|
|||||||
import sonia.scm.repository.RepositoryLocationResolver;
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
import sonia.scm.repository.api.ExportFailedException;
|
import sonia.scm.repository.api.ExportFailedException;
|
||||||
import sonia.scm.xml.XmlStreams;
|
import sonia.scm.xml.XmlStreams;
|
||||||
|
import sonia.scm.xml.XmlStreams.AutoCloseableXMLReader;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
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;
|
||||||
@@ -136,9 +134,7 @@ public class FileStoreExporter implements StoreExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StoreType determineConfigType(Path storePath) {
|
private StoreType determineConfigType(Path storePath) {
|
||||||
XMLStreamReader reader = null;
|
try (AutoCloseableXMLReader reader = XmlStreams.createReader(storePath)) {
|
||||||
try (Reader inputReader = Files.newBufferedReader(storePath, StandardCharsets.UTF_8)) {
|
|
||||||
reader = XmlStreams.createReader(inputReader);
|
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
if (
|
if (
|
||||||
"configuration".equals(reader.getLocalName())
|
"configuration".equals(reader.getLocalName())
|
||||||
@@ -150,8 +146,6 @@ public class FileStoreExporter implements StoreExporter {
|
|||||||
}
|
}
|
||||||
} catch (XMLStreamException | IOException e) {
|
} catch (XMLStreamException | IOException e) {
|
||||||
throw new ExportFailedException(noContext(), "Failed to read store file " + storePath, e);
|
throw new ExportFailedException(noContext(), "Failed to read store file " + storePath, e);
|
||||||
} finally {
|
|
||||||
XmlStreams.close(reader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,18 +29,14 @@ import com.google.common.collect.Maps;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import sonia.scm.security.KeyGenerator;
|
import sonia.scm.security.KeyGenerator;
|
||||||
import sonia.scm.xml.IndentXMLStreamWriter;
|
|
||||||
import sonia.scm.xml.XmlStreams;
|
import sonia.scm.xml.XmlStreams;
|
||||||
|
import sonia.scm.xml.XmlStreams.AutoCloseableXMLReader;
|
||||||
|
import sonia.scm.xml.XmlStreams.AutoCloseableXMLWriter;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBElement;
|
import javax.xml.bind.JAXBElement;
|
||||||
import javax.xml.bind.Marshaller;
|
import javax.xml.bind.Marshaller;
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
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;
|
||||||
@@ -141,10 +137,7 @@ public class JAXBConfigurationEntryStore<V> implements ConfigurationEntryStore<V
|
|||||||
LOG.debug("load configuration from {}", file);
|
LOG.debug("load configuration from {}", file);
|
||||||
|
|
||||||
context.withUnmarshaller(u -> {
|
context.withUnmarshaller(u -> {
|
||||||
XMLStreamReader reader = null;
|
try (AutoCloseableXMLReader reader = XmlStreams.createReader(file)) {
|
||||||
|
|
||||||
try (Reader inputReader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
|
|
||||||
reader = XmlStreams.createReader(inputReader);
|
|
||||||
|
|
||||||
// configuration
|
// configuration
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
@@ -181,8 +174,6 @@ public class JAXBConfigurationEntryStore<V> implements ConfigurationEntryStore<V
|
|||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
XmlStreams.close(reader);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -191,12 +182,11 @@ public class JAXBConfigurationEntryStore<V> implements ConfigurationEntryStore<V
|
|||||||
LOG.debug("store configuration to {}", file);
|
LOG.debug("store configuration to {}", file);
|
||||||
|
|
||||||
context.withMarshaller(m -> {
|
context.withMarshaller(m -> {
|
||||||
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
|
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
|
||||||
|
|
||||||
CopyOnWrite.withTemporaryFile(
|
CopyOnWrite.withTemporaryFile(
|
||||||
temp -> {
|
temp -> {
|
||||||
try (Writer ioWriter = Files.newBufferedWriter(temp, StandardCharsets.UTF_8);
|
try (AutoCloseableXMLWriter writer = XmlStreams.createWriter(temp)) {
|
||||||
IndentXMLStreamWriter writer = XmlStreams.createWriter(ioWriter)) {
|
|
||||||
writer.writeStartDocument();
|
writer.writeStartDocument();
|
||||||
|
|
||||||
// configuration start
|
// configuration start
|
||||||
@@ -217,7 +207,7 @@ public class JAXBConfigurationEntryStore<V> implements ConfigurationEntryStore<V
|
|||||||
|
|
||||||
// value
|
// value
|
||||||
JAXBElement<V> je = new JAXBElement<>(QName.valueOf(TAG_VALUE), type,
|
JAXBElement<V> je = new JAXBElement<>(QName.valueOf(TAG_VALUE), type,
|
||||||
e.getValue());
|
e.getValue());
|
||||||
|
|
||||||
m.marshal(je, writer);
|
m.marshal(je, writer);
|
||||||
|
|
||||||
|
|||||||
@@ -21,19 +21,27 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sonia.scm.xml;
|
package sonia.scm.xml;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.xml.namespace.NamespaceContext;
|
||||||
import javax.xml.stream.XMLInputFactory;
|
import javax.xml.stream.XMLInputFactory;
|
||||||
import javax.xml.stream.XMLOutputFactory;
|
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 javax.xml.stream.util.StreamReaderDelegate;
|
||||||
|
import java.io.Closeable;
|
||||||
|
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 {
|
||||||
|
|
||||||
@@ -62,13 +70,226 @@ public final class XmlStreams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XMLStreamReader createReader(Reader reader) throws XMLStreamException {
|
public static AutoCloseableXMLReader createReader(Path path) throws IOException, XMLStreamException {
|
||||||
XMLInputFactory factory = XMLInputFactory.newInstance();
|
return createReader(Files.newBufferedReader(path, StandardCharsets.UTF_8));
|
||||||
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
|
|
||||||
return factory.createXMLStreamReader(reader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IndentXMLStreamWriter createWriter(Writer writer) throws XMLStreamException {
|
public static AutoCloseableXMLReader createReader(File file) throws IOException, XMLStreamException {
|
||||||
return new IndentXMLStreamWriter(XMLOutputFactory.newFactory().createXMLStreamWriter(writer));
|
return createReader(file.toPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AutoCloseableXMLReader createReader(Reader reader) throws XMLStreamException {
|
||||||
|
XMLInputFactory factory = XMLInputFactory.newInstance();
|
||||||
|
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
|
||||||
|
XMLStreamReader xmlStreamReader = factory.createXMLStreamReader(reader);
|
||||||
|
return new AutoCloseableXMLReader(xmlStreamReader, reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AutoCloseableXMLWriter createWriter(Path path) throws IOException, XMLStreamException {
|
||||||
|
return createWriter(Files.newBufferedWriter(path, StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AutoCloseableXMLWriter createWriter(File file) throws IOException, XMLStreamException {
|
||||||
|
return createWriter(file.toPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AutoCloseableXMLWriter createWriter(Writer writer) throws XMLStreamException {
|
||||||
|
IndentXMLStreamWriter indentXMLStreamWriter = new IndentXMLStreamWriter(XMLOutputFactory.newFactory().createXMLStreamWriter(writer));
|
||||||
|
return new AutoCloseableXMLWriter(indentXMLStreamWriter, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class AutoCloseableXMLReader extends StreamReaderDelegate implements AutoCloseable {
|
||||||
|
|
||||||
|
private final Closeable closeable;
|
||||||
|
|
||||||
|
public AutoCloseableXMLReader(XMLStreamReader delegate, Closeable closeable) {
|
||||||
|
super(delegate);
|
||||||
|
this.closeable = closeable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws XMLStreamException {
|
||||||
|
super.close();
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new XMLStreamException("failed to close nested reader", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class AutoCloseableXMLWriter implements XMLStreamWriter, AutoCloseable {
|
||||||
|
private final XMLStreamWriter delegate;
|
||||||
|
private final Closeable closeable;
|
||||||
|
|
||||||
|
public AutoCloseableXMLWriter(XMLStreamWriter delegate, Closeable closeable) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.closeable = closeable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeStartElement(String localName) throws XMLStreamException {
|
||||||
|
delegate.writeStartElement(localName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
|
||||||
|
delegate.writeStartElement(namespaceURI, localName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
|
||||||
|
delegate.writeStartElement(prefix, localName, namespaceURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
|
||||||
|
delegate.writeEmptyElement(namespaceURI, localName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
|
||||||
|
delegate.writeEmptyElement(prefix, localName, namespaceURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeEmptyElement(String localName) throws XMLStreamException {
|
||||||
|
delegate.writeEmptyElement(localName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeEndElement() throws XMLStreamException {
|
||||||
|
delegate.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeEndDocument() throws XMLStreamException {
|
||||||
|
delegate.writeEndDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws XMLStreamException {
|
||||||
|
delegate.close();
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new XMLStreamException("failed to close nested writer", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() throws XMLStreamException {
|
||||||
|
delegate.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeAttribute(String localName, String value) throws XMLStreamException {
|
||||||
|
delegate.writeAttribute(localName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
|
||||||
|
delegate.writeAttribute(prefix, namespaceURI, localName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
|
||||||
|
delegate.writeAttribute(namespaceURI, localName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
|
||||||
|
delegate.writeNamespace(prefix, namespaceURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
|
||||||
|
delegate.writeDefaultNamespace(namespaceURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeComment(String data) throws XMLStreamException {
|
||||||
|
delegate.writeComment(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeProcessingInstruction(String target) throws XMLStreamException {
|
||||||
|
delegate.writeProcessingInstruction(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
|
||||||
|
delegate.writeProcessingInstruction(target, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeCData(String data) throws XMLStreamException {
|
||||||
|
delegate.writeCData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeDTD(String dtd) throws XMLStreamException {
|
||||||
|
delegate.writeDTD(dtd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeEntityRef(String name) throws XMLStreamException {
|
||||||
|
delegate.writeEntityRef(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeStartDocument() throws XMLStreamException {
|
||||||
|
delegate.writeStartDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeStartDocument(String version) throws XMLStreamException {
|
||||||
|
delegate.writeStartDocument(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
|
||||||
|
delegate.writeStartDocument(encoding, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeCharacters(String text) throws XMLStreamException {
|
||||||
|
delegate.writeCharacters(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
|
||||||
|
delegate.writeCharacters(text, start, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrefix(String uri) throws XMLStreamException {
|
||||||
|
return delegate.getPrefix(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPrefix(String prefix, String uri) throws XMLStreamException {
|
||||||
|
delegate.setPrefix(prefix, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDefaultNamespace(String uri) throws XMLStreamException {
|
||||||
|
delegate.setDefaultNamespace(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
|
||||||
|
delegate.setNamespaceContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NamespaceContext getNamespaceContext() {
|
||||||
|
return delegate.getNamespaceContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getProperty(String name) throws IllegalArgumentException {
|
||||||
|
return delegate.getProperty(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ import sonia.scm.migration.UpdateException;
|
|||||||
import sonia.scm.store.CopyOnWrite;
|
import sonia.scm.store.CopyOnWrite;
|
||||||
import sonia.scm.version.Version;
|
import sonia.scm.version.Version;
|
||||||
import sonia.scm.xml.XmlStreams;
|
import sonia.scm.xml.XmlStreams;
|
||||||
|
import sonia.scm.xml.XmlStreams.AutoCloseableXMLReader;
|
||||||
|
|
||||||
import javax.xml.XMLConstants;
|
import javax.xml.XMLConstants;
|
||||||
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.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;
|
||||||
@@ -45,8 +45,6 @@ import javax.xml.transform.stream.StreamResult;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
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;
|
||||||
@@ -75,9 +73,7 @@ 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;
|
try (AutoCloseableXMLReader reader = XmlStreams.createReader(potentialFile)) {
|
||||||
try (Reader inputReader = Files.newBufferedReader(potentialFile, StandardCharsets.UTF_8)) {
|
|
||||||
reader = XmlStreams.createReader(inputReader);
|
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
if ("configuration".equals(reader.getLocalName())) {
|
if ("configuration".equals(reader.getLocalName())) {
|
||||||
reader.nextTag();
|
reader.nextTag();
|
||||||
@@ -87,8 +83,6 @@ abstract class DifferentiateBetweenConfigAndConfigEntryUpdateStep {
|
|||||||
}
|
}
|
||||||
} catch (XMLStreamException | IOException e) {
|
} catch (XMLStreamException | IOException e) {
|
||||||
throw new UpdateException("Error reading file " + potentialFile, e);
|
throw new UpdateException("Error reading file " + potentialFile, e);
|
||||||
} finally {
|
|
||||||
XmlStreams.close(reader);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -106,12 +100,11 @@ abstract class DifferentiateBetweenConfigAndConfigEntryUpdateStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeXmlDocument(Document configEntryDocument, Path temporaryFile) throws TransformerException {
|
private void writeXmlDocument(Document configEntryDocument, Path temporaryFile) throws TransformerException {
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||||
|
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
||||||
|
DOMSource domSource = new DOMSource(configEntryDocument);
|
||||||
try (OutputStream os = Files.newOutputStream(temporaryFile)) {
|
try (OutputStream os = Files.newOutputStream(temporaryFile)) {
|
||||||
final TransformerFactory factory = TransformerFactory.newInstance();
|
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
|
||||||
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
|
||||||
final DOMSource domSource = new DOMSource(configEntryDocument);
|
|
||||||
|
|
||||||
factory.newTransformer().transform(domSource, new StreamResult(os));
|
factory.newTransformer().transform(domSource, new StreamResult(os));
|
||||||
} 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);
|
||||||
|
|||||||
Reference in New Issue
Block a user