X Tutup
Skip to content

Commit 576f6fd

Browse files
committed
StaxEventContentHandler uses static inner class for Location adapter, in order to avoid leaks when caching events
Issue: SPR-9305
1 parent 5204e11 commit 576f6fd

File tree

1 file changed

+61
-54
lines changed

1 file changed

+61
-54
lines changed
Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,119 +32,99 @@
3232
import org.xml.sax.Attributes;
3333
import org.xml.sax.Locator;
3434

35-
import org.springframework.util.Assert;
3635
import org.springframework.util.StringUtils;
3736

3837
/**
39-
* SAX <code>ContentHandler</code> that transforms callback calls to <code>XMLEvent</code>s and writes them to a
40-
* <code>XMLEventConsumer</code>.
38+
* SAX <code>ContentHandler</code> that transforms callback calls to <code>XMLEvent</code>s
39+
* and writes them to a <code>XMLEventConsumer</code>.
4140
*
4241
* @author Arjen Poutsma
42+
* @since 3.0
4343
* @see XMLEvent
4444
* @see XMLEventConsumer
45-
* @since 3.0
4645
*/
4746
class StaxEventContentHandler extends AbstractStaxContentHandler {
4847

4948
private final XMLEventFactory eventFactory;
5049

5150
private final XMLEventConsumer eventConsumer;
5251

52+
5353
/**
54-
* Constructs a new instance of the <code>StaxEventContentHandler</code> that writes to the given
54+
* Construct a new instance of the <code>StaxEventContentHandler</code> that writes to the given
5555
* <code>XMLEventConsumer</code>. A default <code>XMLEventFactory</code> will be created.
56-
*
5756
* @param consumer the consumer to write events to
5857
*/
5958
StaxEventContentHandler(XMLEventConsumer consumer) {
60-
Assert.notNull(consumer, "'consumer' must not be null");
61-
eventFactory = XMLEventFactory.newInstance();
62-
eventConsumer = consumer;
59+
this.eventFactory = XMLEventFactory.newInstance();
60+
this.eventConsumer = consumer;
6361
}
6462

6563
/**
66-
* Constructs a new instance of the <code>StaxEventContentHandler</code> that uses the given event factory to create
67-
* events and writes to the given <code>XMLEventConsumer</code>.
68-
*
64+
* Construct a new instance of the <code>StaxEventContentHandler</code> that uses the given
65+
* event factory to create events and writes to the given <code>XMLEventConsumer</code>.
6966
* @param consumer the consumer to write events to
7067
* @param factory the factory used to create events
7168
*/
7269
StaxEventContentHandler(XMLEventConsumer consumer, XMLEventFactory factory) {
73-
eventFactory = factory;
74-
eventConsumer = consumer;
70+
this.eventFactory = factory;
71+
this.eventConsumer = consumer;
7572
}
7673

77-
public void setDocumentLocator(final Locator locator) {
74+
public void setDocumentLocator(Locator locator) {
7875
if (locator != null) {
79-
eventFactory.setLocation(new Location() {
80-
81-
public int getLineNumber() {
82-
return locator.getLineNumber();
83-
}
84-
85-
public int getColumnNumber() {
86-
return locator.getColumnNumber();
87-
}
88-
89-
public int getCharacterOffset() {
90-
return -1;
91-
}
92-
93-
public String getPublicId() {
94-
return locator.getPublicId();
95-
}
96-
97-
public String getSystemId() {
98-
return locator.getSystemId();
99-
}
100-
});
76+
this.eventFactory.setLocation(new LocatorLocationAdapter(locator));
10177
}
10278
}
10379

10480
@Override
10581
protected void startDocumentInternal() throws XMLStreamException {
106-
consumeEvent(eventFactory.createStartDocument());
82+
consumeEvent(this.eventFactory.createStartDocument());
10783
}
10884

10985
@Override
11086
protected void endDocumentInternal() throws XMLStreamException {
111-
consumeEvent(eventFactory.createEndDocument());
87+
consumeEvent(this.eventFactory.createEndDocument());
11288
}
11389

11490
@Override
11591
protected void startElementInternal(QName name, Attributes atts, SimpleNamespaceContext namespaceContext)
11692
throws XMLStreamException {
93+
11794
List attributes = getAttributes(atts);
11895
List namespaces = createNamespaces(namespaceContext);
119-
consumeEvent(eventFactory.createStartElement(name, attributes.iterator(), namespaces != null ? namespaces.iterator() : null));
96+
consumeEvent(this.eventFactory.createStartElement(name, attributes.iterator(),
97+
(namespaces != null ? namespaces.iterator() : null)));
12098
}
12199

122100
@Override
123101
protected void endElementInternal(QName name, SimpleNamespaceContext namespaceContext) throws XMLStreamException {
124102
List namespaces = createNamespaces(namespaceContext);
125-
consumeEvent(eventFactory.createEndElement(name, namespaces != null ? namespaces.iterator() : null));
103+
consumeEvent(this.eventFactory.createEndElement(name, namespaces != null ? namespaces.iterator() : null));
126104
}
127105

128106
@Override
129107
protected void charactersInternal(char[] ch, int start, int length) throws XMLStreamException {
130-
consumeEvent(eventFactory.createCharacters(new String(ch, start, length)));
108+
consumeEvent(this.eventFactory.createCharacters(new String(ch, start, length)));
131109
}
132110

133111
@Override
134112
protected void ignorableWhitespaceInternal(char[] ch, int start, int length) throws XMLStreamException {
135-
consumeEvent(eventFactory.createIgnorableSpace(new String(ch, start, length)));
113+
consumeEvent(this.eventFactory.createIgnorableSpace(new String(ch, start, length)));
136114
}
137115

138116
@Override
139117
protected void processingInstructionInternal(String target, String data) throws XMLStreamException {
140-
consumeEvent(eventFactory.createProcessingInstruction(target, data));
118+
consumeEvent(this.eventFactory.createProcessingInstruction(target, data));
141119
}
142120

143121
private void consumeEvent(XMLEvent event) throws XMLStreamException {
144-
eventConsumer.add(event);
122+
this.eventConsumer.add(event);
145123
}
146124

147-
/** Creates and returns a list of <code>NameSpace</code> objects from the <code>NamespaceContext</code>. */
125+
/**
126+
* Create and return a list of <code>NameSpace</code> objects from the <code>NamespaceContext</code>.
127+
*/
148128
private List<Namespace> createNamespaces(SimpleNamespaceContext namespaceContext) {
149129
if (namespaceContext == null) {
150130
return null;
@@ -153,12 +133,12 @@ private List<Namespace> createNamespaces(SimpleNamespaceContext namespaceContext
153133
List<Namespace> namespaces = new ArrayList<Namespace>();
154134
String defaultNamespaceUri = namespaceContext.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX);
155135
if (StringUtils.hasLength(defaultNamespaceUri)) {
156-
namespaces.add(eventFactory.createNamespace(defaultNamespaceUri));
136+
namespaces.add(this.eventFactory.createNamespace(defaultNamespaceUri));
157137
}
158138
for (Iterator iterator = namespaceContext.getBoundPrefixes(); iterator.hasNext();) {
159139
String prefix = (String) iterator.next();
160140
String namespaceUri = namespaceContext.getNamespaceURI(prefix);
161-
namespaces.add(eventFactory.createNamespace(prefix, namespaceUri));
141+
namespaces.add(this.eventFactory.createNamespace(prefix, namespaceUri));
162142
}
163143
return namespaces;
164144
}
@@ -168,18 +148,45 @@ private List<Attribute> getAttributes(Attributes attributes) {
168148
for (int i = 0; i < attributes.getLength(); i++) {
169149
QName name = toQName(attributes.getURI(i), attributes.getQName(i));
170150
if (!("xmlns".equals(name.getLocalPart()) || "xmlns".equals(name.getPrefix()))) {
171-
list.add(eventFactory.createAttribute(name, attributes.getValue(i)));
151+
list.add(this.eventFactory.createAttribute(name, attributes.getValue(i)));
172152
}
173153
}
174154
return list;
175155
}
176156

177-
//
178-
// No operation
179-
//
180-
157+
/* No operation */
181158
@Override
182159
protected void skippedEntityInternal(String name) throws XMLStreamException {
183160
}
184161

162+
163+
private static final class LocatorLocationAdapter implements Location {
164+
165+
private final Locator locator;
166+
167+
public LocatorLocationAdapter(Locator locator) {
168+
this.locator = locator;
169+
}
170+
171+
public int getLineNumber() {
172+
return this.locator.getLineNumber();
173+
}
174+
175+
public int getColumnNumber() {
176+
return this.locator.getColumnNumber();
177+
}
178+
179+
public int getCharacterOffset() {
180+
return -1;
181+
}
182+
183+
public String getPublicId() {
184+
return this.locator.getPublicId();
185+
}
186+
187+
public String getSystemId() {
188+
return this.locator.getSystemId();
189+
}
190+
}
191+
185192
}

0 commit comments

Comments
 (0)
X Tutup