diff --git a/src/main/java/net/fortuna/ical4j/data/DefaultContentHandler.java b/src/main/java/net/fortuna/ical4j/data/DefaultContentHandler.java index 3cdec6157..c95b856d8 100644 --- a/src/main/java/net/fortuna/ical4j/data/DefaultContentHandler.java +++ b/src/main/java/net/fortuna/ical4j/data/DefaultContentHandler.java @@ -14,6 +14,7 @@ import java.net.URISyntaxException; import java.text.ParseException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; @@ -38,9 +39,10 @@ public class DefaultContentHandler implements ContentHandler { private PropertyBuilder propertyBuilder; - private ComponentBuilder componentBuilder; - - private ComponentBuilder subComponentBuilder; + /** + * The current component builders. + */ + private final LinkedList> components = new LinkedList<>(); private Calendar calendar; @@ -61,9 +63,21 @@ public DefaultContentHandler(Consumer consumer, TimeZoneRegistry tzReg this.componentFactorySupplier = componentFactorySupplier; } + public ComponentBuilder getComponentBuilder() { + if (components.size() == 0) { + return null; + } + return components.peek(); + } + + public void endComponent() { + components.pop(); + } + @Override public void startCalendar() { calendar = new Calendar(); + components.clear(); propertiesWithTzId = new ArrayList<>(); } @@ -76,24 +90,31 @@ public void endCalendar() throws IOException { @Override public void startComponent(String name) { - if (componentBuilder != null) { - subComponentBuilder = new ComponentBuilder<>(); - subComponentBuilder.factories(componentFactorySupplier.get()).name(name); - } else { - componentBuilder = new ComponentBuilder<>(); - componentBuilder.factories(componentFactorySupplier.get()).name(name); + if (components.size() > 10) { + throw new RuntimeException("Components nested too deep"); } + + ComponentBuilder componentBuilder = + new ComponentBuilder<>(); + componentBuilder.factories(componentFactorySupplier.get()).name(name); + components.push(componentBuilder); } @Override public void endComponent(String name) { - assertComponent(componentBuilder); + assertComponent(getComponentBuilder()); + + final ComponentBuilder componentBuilder = + getComponentBuilder(); - if (subComponentBuilder != null) { - Component subComponent = subComponentBuilder.build(); - componentBuilder.subComponent(subComponent); + DefaultContentHandler.this.endComponent(); - subComponentBuilder = null; + final ComponentBuilder parent = + getComponentBuilder(); + + if (parent != null) { + Component subComponent = componentBuilder.build(); + parent.subComponent(subComponent); } else { CalendarComponent component = componentBuilder.build(); calendar.getComponents().add(component); @@ -101,8 +122,6 @@ public void endComponent(String name) { // register the timezone for use with iCalendar objects.. tzRegistry.register(new TimeZone((VTimeZone) component)); } - - componentBuilder = null; } } @@ -127,12 +146,8 @@ public void endProperty(String name) throws URISyntaxException, ParseException, } // replace with a constant instance if applicable.. property = Constants.forProperty(property); - if (componentBuilder != null) { - if (subComponentBuilder != null) { - subComponentBuilder.property(property); - } else { - componentBuilder.property(property); - } + if (getComponentBuilder() != null) { + getComponentBuilder().property(property); } else if (calendar != null) { calendar.getProperties().add(property); }