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

Feat: Add buffering of InputStream for EPSG-parsing

parent 87cf6a6c
Showing with 50 additions and 5 deletions
+50 -5
......@@ -204,26 +204,46 @@ public class CityGmlParser {
CityGMLContext context = getContext();
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.");
}
try {
parseEpsgCodeFromStream(is, config);
BufferedInputStream bis = new BufferedInputStream(is);
readEpsgCodeFromInputStream(bis,config);
CityGMLInputFactory in = context.createCityGMLInputFactory()
.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){
ois.addListener(l::updateProgress);
}
return readAndKeepFeatures(config, Path.of(""), in, ois);
}
} catch (CityGMLReadException | IOException | ParserConfigurationException | SAXException e) {
logger.error(e);
} catch (CityGMLReadException | IOException 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,
String outputFile) throws CityGmlParseException {
Path f = Paths.get(file);
......@@ -438,6 +458,31 @@ public class CityGmlParser {
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){
logger.debug("Exception while parsing for EPSG code", e);
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