Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
charphi committed May 9, 2023
2 parents b05ddf6 + 420d3f4 commit a99568d
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 157 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.0.22] - 2023-05-09

### Fixed

- Fix EOF detection on non-empty XML files

## [0.0.21] - 2023-04-18

### Added
Expand Down Expand Up @@ -196,7 +202,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

- Initial release

[Unreleased]: https://github.com/nbbrd/java-io-util/compare/v0.0.21...HEAD
[Unreleased]: https://github.com/nbbrd/java-io-util/compare/v0.0.22...HEAD
[0.0.22]: https://github.com/nbbrd/java-io-util/compare/v0.0.21...v0.0.22
[0.0.21]: https://github.com/nbbrd/java-io-util/compare/v0.0.20...v0.0.21
[0.0.20]: https://github.com/nbbrd/java-io-util/compare/v0.0.19...v0.0.20
[0.0.19]: https://github.com/nbbrd/java-io-util/compare/v0.0.18...v0.0.19
Expand Down
2 changes: 1 addition & 1 deletion java-io-base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.github.nbbrd.java-io-util</groupId>
<artifactId>java-io-parent</artifactId>
<version>0.0.21</version>
<version>0.0.22</version>
</parent>

<artifactId>java-io-base</artifactId>
Expand Down
15 changes: 9 additions & 6 deletions java-io-base/src/main/java/internal/io/text/LegacyFiles.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.AccessDeniedException;
import java.nio.file.FileSystemException;
import java.nio.file.NoSuchFileException;
Expand Down Expand Up @@ -92,16 +93,18 @@ public static void checkIsFile(@NonNull File source) throws FileSystemException
}
}

public String toSystemId(File file) {
public String toSystemId(@NonNull File file) {
return file.toURI().toASCIIString();
}

public File fromSystemId(String systemId) {
try {
return new File(URI.create(systemId));
} catch (IllegalArgumentException ex) {
return null;
public File fromSystemId(@NonNull String systemId) {
if (systemId.startsWith("file:/")) {
try {
return new File(new URI(systemId));
} catch (URISyntaxException ignore) {
}
}
return null;
}

private static <T extends Closeable> T checkResource(T resource, String message) throws IOException {
Expand Down
2 changes: 1 addition & 1 deletion java-io-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>java-io-parent</artifactId>
<groupId>com.github.nbbrd.java-io-util</groupId>
<version>0.0.21</version>
<version>0.0.22</version>
</parent>

<artifactId>java-io-bom</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion java-io-picocsv/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>java-io-parent</artifactId>
<groupId>com.github.nbbrd.java-io-util</groupId>
<version>0.0.21</version>
<version>0.0.22</version>
</parent>

<artifactId>java-io-picocsv</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion java-io-win/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>com.github.nbbrd.java-io-util</groupId>
<artifactId>java-io-parent</artifactId>
<version>0.0.21</version>
<version>0.0.22</version>
</parent>

<artifactId>java-io-win</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion java-io-xml-bind/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.github.nbbrd.java-io-util</groupId>
<artifactId>java-io-parent</artifactId>
<version>0.0.21</version>
<version>0.0.22</version>
</parent>

<artifactId>java-io-xml-bind</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion java-io-xml/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.github.nbbrd.java-io-util</groupId>
<artifactId>java-io-parent</artifactId>
<version>0.0.21</version>
<version>0.0.22</version>
</parent>

<artifactId>java-io-xml</artifactId>
Expand Down
103 changes: 60 additions & 43 deletions java-io-xml/src/main/java/nbbrd/io/xml/Sax.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static void preventXXE(@NonNull XMLReader reader) {
} catch (ParserConfigurationException ex) {
throw wrapConfigException(ex);
} catch (SAXException ex) {
throw toIOException(ex);
throw wrapSAXException(ex);
}
}

Expand Down Expand Up @@ -90,10 +90,7 @@ public static void preventXXE(@NonNull XMLReader reader) {
}

public static @NonNull IOException toIOException(@NonNull SAXException ex) {
if (ex instanceof SAXParseException) {
return wrapParseException((SAXParseException) ex);
}
return WrappedIOException.wrap(ex);
return wrapSAXException(ex);
}

@lombok.With
Expand Down Expand Up @@ -151,48 +148,53 @@ public final static class Builder<T> {

@Override
public @NonNull T parseFile(@NonNull File source) throws IOException {
return parse(newInputSource(LegacyFiles.checkSource(source)));
return doParse(newInputSource(LegacyFiles.checkSource(source)));
}

@Override
public @NonNull T parseFile(@NonNull File source, @NonNull Charset encoding) throws IOException {
return parse(newInputSource(LegacyFiles.checkSource(source), encoding));
return doParse(newInputSource(LegacyFiles.checkSource(source), encoding));
}

@Override
public @NonNull T parseReader(@NonNull Reader resource) throws IOException {
return parse(new InputSource(resource));
return doParse(new InputSource(resource));
}

@Override
public @NonNull T parseStream(@NonNull InputStream resource) throws IOException {
return parse(new InputSource(resource));
return doParse(new InputSource(resource));
}

@Override
public @NonNull T parseStream(@NonNull InputStream resource, @NonNull Charset encoding) throws IOException {
InputSource input = new InputSource(resource);
input.setEncoding(encoding.name());
return parse(input);
return doParse(input);
}

private T parse(InputSource input) throws IOException {
XMLReader engine = factory.getWithIO();
if (!ignoreXXE) {
preventXXE(engine);
}
engine.setContentHandler(contentHandler);
engine.setDTDHandler(dtdHandler);
engine.setEntityResolver(entityResolver);
engine.setErrorHandler(errorHandler);
private T doParse(InputSource input) throws IOException {
XMLReader engine = getEngine();
before.runWithIO();
try {
engine.parse(input);
} catch (SAXException ex) {
throw toIOException(ex);
throw wrapSAXException(ex);
}
return after.getWithIO();
}

private XMLReader getEngine() throws IOException {
XMLReader result = factory.getWithIO();
if (!ignoreXXE) {
preventXXE(result);
}
result.setContentHandler(contentHandler);
result.setDTDHandler(dtdHandler);
result.setEntityResolver(entityResolver);
result.setErrorHandler(errorHandler);
return result;
}
}

private final static SAXParserFactory DEFAULT_FACTORY = initFactory();
Expand All @@ -212,46 +214,61 @@ private static void disableFeature(XMLReader reader, String feature) {
}
}

private static IOException wrapSAXException(SAXException ex) {
if (ex instanceof SAXParseException) {
return wrapParseException((SAXParseException) ex);
}
return WrappedIOException.wrap(ex);
}

private static IOException wrapConfigException(ParserConfigurationException ex) {
return WrappedIOException.wrap(ex);
}

private static IOException wrapParseException(SAXParseException ex) {
if (isEOF(ex)) {
if (SaxEOF.isEOF(ex)) {
return new EOFException(Objects.toString(getFileOrNull(ex)));
}
return WrappedIOException.wrap(ex);
}

private static boolean isEOF(SAXParseException ex) {
return ex.getMessage() != null && isEOFMessage(ex.getMessage());
private static File getFileOrNull(SAXParseException ex) {
String systemId = ex.getSystemId();
if (systemId == null) return null;
return LegacyFiles.fromSystemId(systemId);
}

private static boolean isEOFMessage(String message) {
return EOF_MESSAGES.computeIfAbsent(Locale.getDefault(), Sax::loadEOFMessage).equals(message);
}
private static final String SAX_FEATURES_EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
private static final String SAX_FEATURES_EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
private static final String XERCES_FEATURES_NONVALIDATING_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";

private static String loadEOFMessage(Locale locale) {
try {
private static final class SaxEOF {

private static boolean isEOF(SAXParseException ex) {
return ex.getMessage() != null && isEOFMessage(ex.getMessage());
}

private static boolean isEOFMessage(String message) {
return EOF_MESSAGE_BY_LOCALE.computeIfAbsent(Locale.getDefault(), SaxEOF::loadEOFMessage).equals(message);
}

private static String loadEOFMessage(Locale locale) {
try {
parseEmptyContent(locale);
} catch (IOException | SAXException | ParserConfigurationException e) {
if (e instanceof SAXParseException) {
return e.getMessage();
}
}
return "Premature end of file.";
}

private static void parseEmptyContent(Locale ignore) throws SAXException, ParserConfigurationException, IOException {
XMLReader reader = DEFAULT_FACTORY.newSAXParser().getXMLReader();
reader.setErrorHandler(new DefaultHandler());
reader.parse(new InputSource(new StringReader("")));
} catch (IOException | SAXException | ParserConfigurationException e) {
if (e instanceof SAXParseException) {
return e.getMessage();
}
}
return "Premature end of file.";
}

private static final ConcurrentHashMap<Locale, String> EOF_MESSAGES = new ConcurrentHashMap<>();

private static File getFileOrNull(SAXParseException ex) {
String result = ex.getSystemId();
return result != null && result.startsWith("file:/") ? LegacyFiles.fromSystemId(result) : null;
private static final ConcurrentHashMap<Locale, String> EOF_MESSAGE_BY_LOCALE = new ConcurrentHashMap<>();
}

private static final String SAX_FEATURES_EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
private static final String SAX_FEATURES_EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
private static final String XERCES_FEATURES_NONVALIDATING_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
}
Loading

0 comments on commit a99568d

Please sign in to comment.