Commit 90ebc78e authored by Riegel's avatar Riegel
Browse files

Feat: Add buffering of InputStream for EPSG-parsing

2 merge requests!28Version 3.17.0 Release,!26Add ZIP-archive support
Showing with 50 additions and 5 deletions
+50 -5
...@@ -204,26 +204,46 @@ public class CityGmlParser { ...@@ -204,26 +204,46 @@ public class CityGmlParser {
CityGMLContext context = getContext(); CityGMLContext context = getContext();
if (config.getValidate()) { if (config.getValidate()) {
//TODO: Think of something to validate Inputstream //TODO: Think of something to XML-validate Inputstream
//XML validation requires looking at nesting of tags
//not a problem for small files, but big files will run into memory limit and crash
// Maybe do it dirty by writing stream to temp file and passing it to parseCityGmlFile()?
throw new InvalidGmlFileException("Invalid GML File."); throw new InvalidGmlFileException("Invalid GML File.");
} }
try { try {
parseEpsgCodeFromStream(is, config); BufferedInputStream bis = new BufferedInputStream(is);
readEpsgCodeFromInputStream(bis,config);
CityGMLInputFactory in = context.createCityGMLInputFactory() CityGMLInputFactory in = context.createCityGMLInputFactory()
.withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false)); .withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(false));
try(ObservedInputStream ois = new ObservedInputStream(is, is.available())){ try(ObservedInputStream ois = new ObservedInputStream(bis, bis.available())){
if (l != null){ if (l != null){
ois.addListener(l::updateProgress); ois.addListener(l::updateProgress);
} }
return readAndKeepFeatures(config, Path.of(""), in, ois); return readAndKeepFeatures(config, Path.of(""), in, ois);
} }
} catch (CityGMLReadException | IOException | ParserConfigurationException | SAXException e) { } catch (CityGMLReadException | IOException e) {
logger.error(e);
throw new CityGmlParseException("Failed to read CityGML file", e); throw new CityGmlParseException("Failed to read CityGML file", e);
} }
} }
private static void readEpsgCodeFromInputStream(BufferedInputStream bis, ParserConfiguration config) throws CityGmlParseException {
try{
// Mark start position of GML-"file"
bis.mark(Integer.MAX_VALUE);
// Buffer the first 10000 chars of the Stream, EPSG/envelope info should be found within that range
int peekingWidth = Math.min(10000, bis.available());
byte[] buf = new byte[peekingWidth];
bis.read(buf, 0, peekingWidth);
bis.reset();
parseEpsgCodeFromBuffer(buf, config);
} catch (ParserConfigurationException | SAXException | IOException e) {
throw new CityGmlParseException("Failed to read CityGML file", e);
}
}
public static void streamCityGml(String file, ParserConfiguration config, CityGmlConsumer cityObjectConsumer, public static void streamCityGml(String file, ParserConfiguration config, CityGmlConsumer cityObjectConsumer,
String outputFile) throws CityGmlParseException { String outputFile) throws CityGmlParseException {
Path f = Paths.get(file); Path f = Paths.get(file);
...@@ -438,6 +458,31 @@ public class CityGmlParser { ...@@ -438,6 +458,31 @@ public class CityGmlParser {
logEpsgParseError(e); logEpsgParseError(e);
} }
} }
private static void parseEpsgCodeFromBuffer(byte[] buffer, ParserConfiguration config)
throws ParserConfigurationException, SAXException {
InputStream is = new ByteArrayInputStream(buffer);
SAXParser parser = FACTORY.newSAXParser();
CityGmlHandler handler = new CityGmlHandler();
try {
parser.parse(new InputSource(is), handler);
} catch (EnvelopeFoundException e) {
try {
parseCoordinateSystem(config, handler);
} catch (Exception e2) {
logEpsgParseError(e2);
}
}catch (SAXParseException spe){
// suppress XML document structure warning
if (!spe.getMessage().matches("XML document structures must start and end within the same entity.")){
logEpsgParseError(spe);
}
}catch (Exception e) {
logEpsgParseError(e);
}
}
private static void logEpsgParseError(Exception e){ private static void logEpsgParseError(Exception e){
logger.debug("Exception while parsing for EPSG code", e); logger.debug("Exception while parsing for EPSG code", e);
if (logger.isWarnEnabled()) { if (logger.isWarnEnabled()) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment