Skip to content

Commit 61f8a54

Browse files
duncdrumcursoragent
andcommitted
[bugfix] Stop Xerces prolog stderr spam during filesystem backup restore
FileSystemBackupDescriptor was parsing every backup payload file as XML when counting resources, which printed [Fatal Error] for binary entries. Count __contents__.xml descriptors only (matching zip backups) and route SAX parse errors through DefaultHandler instead of a null error handler. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 9057c82 commit 61f8a54

3 files changed

Lines changed: 22 additions & 13 deletions

File tree

exist-core/src/main/java/org/exist/backup/DescriptorResourceCounter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public DescriptorResourceCounter() throws ParserConfigurationException, SAXExcep
5656
this.counterHandler = new CounterHandler();
5757

5858
xmlReader.setContentHandler(counterHandler);
59+
// Suppress Xerces "[Fatal Error]" stderr noise; fatal errors still propagate via DefaultHandler.
60+
xmlReader.setErrorHandler(counterHandler);
5961
}
6062

6163
public long count(final InputStream descriptorInputStream) throws IOException, SAXException {

exist-core/src/main/java/org/exist/backup/FileSystemBackupDescriptor.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.xml.sax.SAXException;
3131

3232
import javax.xml.parsers.ParserConfigurationException;
33-
import java.io.BufferedInputStream;
3433
import java.io.FileNotFoundException;
3534
import java.io.IOException;
3635
import java.io.InputStream;
@@ -196,23 +195,25 @@ public Path getRepoBackup() throws IOException {
196195
return null;
197196
}
198197

198+
/**
199+
* Count resources declared in {@link BackupDescriptor#COLLECTION_DESCRIPTOR} files under this
200+
* collection subtree (same approach as {@link ZipArchiveBackupDescriptor}).
201+
*/
199202
private void countFileEntries(final Path descriptor) {
200-
201-
// Only count files from top level.
202-
if (!descriptor.toString().endsWith("/db/" + COLLECTION_DESCRIPTOR)) {
203+
final Path collectionDir = descriptor.getParent();
204+
if (collectionDir == null) {
203205
return;
204206
}
205207

206208
try {
207209
final DescriptorResourceCounter descriptorResourceCounter = new DescriptorResourceCounter();
208210

209-
try (final Stream<Path> walk = Files.walk(descriptor.getParent());
210-
final Stream<Path> ds = walk
211-
.filter(f -> !Files.isDirectory(f))
212-
.filter(f -> !COLLECTION_DESCRIPTOR.equals(f.getFileName().toString()))) {
213-
214-
for (final Path d : ds.collect(Collectors.toList())) {
215-
try (final InputStream is = new BufferedInputStream(Files.newInputStream(d))) {
211+
try (final Stream<Path> walk = Files.walk(collectionDir)) {
212+
for (final Path contentsFile : walk
213+
.filter(p -> !Files.isDirectory(p))
214+
.filter(p -> COLLECTION_DESCRIPTOR.equals(p.getFileName().toString()))
215+
.toList()) {
216+
try (final InputStream is = Files.newInputStream(contentsFile)) {
216217
numberOfFiles += descriptorResourceCounter.count(is);
217218
}
218219
}

exist-core/src/main/java/org/exist/util/XMLReaderObjectFactory.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.xml.sax.SAXNotRecognizedException;
4040
import org.xml.sax.SAXNotSupportedException;
4141
import org.xml.sax.XMLReader;
42+
import org.xml.sax.helpers.DefaultHandler;
4243
import org.xmlresolver.Resolver;
4344

4445
import java.util.Map;
@@ -51,6 +52,9 @@ public class XMLReaderObjectFactory extends BasePooledObjectFactory<XMLReader> i
5152

5253
private static final Logger LOG = LogManager.getLogger(XMLReaderObjectFactory.class);
5354

55+
/** Shared handler: routes parse errors through SAX without Xerces stderr spam. */
56+
private static final DefaultHandler SILENT_SAX_ERROR_HANDLER = new DefaultHandler();
57+
5458
public static final String CONFIGURATION_ENTITY_RESOLVER_ELEMENT_NAME = "entity-resolver";
5559
public static final String CONFIGURATION_CATALOG_ELEMENT_NAME = "catalog";
5660
public static final String CONFIGURATION_ELEMENT_NAME = "validation";
@@ -98,7 +102,7 @@ public XMLReader create() throws Exception {
98102
final SAXParser saxParser = saxParserFactory.newSAXParser();
99103
final XMLReader xmlReader = saxParser.getXMLReader();
100104

101-
xmlReader.setErrorHandler(null); // disable default Xerces Error Handler
105+
xmlReader.setErrorHandler(SILENT_SAX_ERROR_HANDLER);
102106

103107
return xmlReader;
104108
}
@@ -136,14 +140,16 @@ public void activateObject(final PooledObject<XMLReader> pooledXmlReader) {
136140
setReaderFeature(xmlReader, feature.getKey(), feature.getValue());
137141
}
138142
}
143+
144+
xmlReader.setErrorHandler(SILENT_SAX_ERROR_HANDLER);
139145
}
140146

141147
@Override
142148
public void passivateObject(final PooledObject<XMLReader> pooledXmlReader) throws Exception {
143149
final XMLReader xmlReader = pooledXmlReader.getObject();
144150

145151
xmlReader.setContentHandler(null);
146-
xmlReader.setErrorHandler(null);
152+
xmlReader.setErrorHandler(SILENT_SAX_ERROR_HANDLER);
147153
xmlReader.setProperty(Namespaces.SAX_LEXICAL_HANDLER, null);
148154
}
149155

0 commit comments

Comments
 (0)