Skip to content

Commit df18b8f

Browse files
committed
bug(#273): Make Jcabi Greate Again?
1 parent b37b7b1 commit df18b8f

8 files changed

Lines changed: 222 additions & 316 deletions

File tree

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
9292
<version>33.4.0-jre</version>
9393
<scope>test</scope>
9494
</dependency>
95+
<dependency>
96+
<groupId>com.yegor256</groupId>
97+
<artifactId>together</artifactId>
98+
<version>0.0.5</version>
99+
<scope>test</scope>
100+
</dependency>
95101
<dependency>
96102
<groupId>net.sf.saxon</groupId>
97103
<artifactId>Saxon-HE</artifactId>

src/main/java/com/jcabi/xml/ClasspathResolver.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@ final class ClasspathResolver implements LSResourceResolver {
4242

4343
@Override
4444
@SuppressWarnings("PMD.UseObjectForClearerAPI")
45-
// @checkstyle ParameterNumber (1 line)
46-
public LSInput resolveResource(final String type, final String nspace,
47-
final String pid, final String sid, final String base) {
45+
// @checkstyle ParameterNumber (10 lines)
46+
public LSInput resolveResource(
47+
final String type,
48+
final String nspace,
49+
final String pid,
50+
final String sid,
51+
final String base
52+
) {
4853
LSInput input = null;
49-
final ClassLoader loader =
50-
Thread.currentThread().getContextClassLoader();
54+
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
5155
if (sid != null && loader.getResource(sid) != null) {
5256
input = new ClasspathInput(pid, sid);
5357
}
5458
return input;
5559
}
56-
5760
}

src/main/java/com/jcabi/xml/SaxonDocument.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import net.sf.saxon.s9api.XdmItem;
5151
import net.sf.saxon.s9api.XdmNode;
5252
import org.w3c.dom.Node;
53+
import org.w3c.dom.ls.LSResourceResolver;
5354
import org.xml.sax.SAXParseException;
5455

5556
/**
@@ -228,7 +229,7 @@ public Node deepCopy() {
228229
}
229230

230231
@Override
231-
public Collection<SAXParseException> validate() {
232+
public Collection<SAXParseException> validate(final LSResourceResolver resolver) {
232233
throw new UnsupportedOperationException(
233234
String.format(SaxonDocument.UNSUPPORTED, "validate")
234235
);

src/main/java/com/jcabi/xml/StrictXML.java

Lines changed: 4 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,17 @@
3030
package com.jcabi.xml;
3131

3232
import com.jcabi.log.Logger;
33-
import java.io.IOException;
34-
import java.net.SocketException;
3533
import java.util.ArrayList;
3634
import java.util.Collection;
3735
import java.util.Iterator;
3836
import java.util.List;
39-
import java.util.concurrent.CopyOnWriteArrayList;
40-
import javax.xml.XMLConstants;
4137
import javax.xml.namespace.NamespaceContext;
42-
import javax.xml.transform.dom.DOMSource;
43-
import javax.xml.validation.SchemaFactory;
44-
import javax.xml.validation.Validator;
4538
import lombok.EqualsAndHashCode;
4639
import org.cactoos.Scalar;
4740
import org.cactoos.scalar.Sticky;
4841
import org.cactoos.scalar.Unchecked;
4942
import org.w3c.dom.Node;
5043
import org.w3c.dom.ls.LSResourceResolver;
51-
import org.xml.sax.SAXException;
5244
import org.xml.sax.SAXParseException;
5345

5446
/**
@@ -84,16 +76,7 @@ public StrictXML(final XML xml) {
8476
* @since 0.19
8577
*/
8678
public StrictXML(final XML xml, final LSResourceResolver resolver) {
87-
this(xml, StrictXML.newValidator(resolver));
88-
}
89-
90-
/**
91-
* Public ctor.
92-
* @param xml XML document
93-
* @param val Custom validator
94-
*/
95-
public StrictXML(final XML xml, final Validator val) {
96-
this(xml, () -> StrictXML.validate(xml, val));
79+
this(xml, () -> xml.validate(resolver));
9780
}
9881

9982
/**
@@ -102,7 +85,7 @@ public StrictXML(final XML xml, final Validator val) {
10285
* @param schema XSD schema
10386
*/
10487
public StrictXML(final XML xml, final XML schema) {
105-
this(xml, () -> StrictXML.check(xml, schema));
88+
this(xml, () -> xml.validate(schema));
10689
}
10790

10891
/**
@@ -193,25 +176,15 @@ public Node deepCopy() {
193176
}
194177

195178
@Override
196-
public Collection<SAXParseException> validate() {
197-
return this.origin.value().validate();
179+
public Collection<SAXParseException> validate(final LSResourceResolver resolver) {
180+
return this.origin.value().validate(resolver);
198181
}
199182

200183
@Override
201184
public Collection<SAXParseException> validate(final XML xsd) {
202185
return this.origin.value().validate(xsd);
203186
}
204187

205-
/**
206-
* Check and return list of errors.
207-
* @param xml The XML to check
208-
* @param xsd Schema to use
209-
* @return List of errors
210-
*/
211-
private static Collection<SAXParseException> check(final XML xml, final XML xsd) {
212-
return xml.validate(xsd);
213-
}
214-
215188
/**
216189
* Convert errors to lines.
217190
* @param errors The errors
@@ -273,64 +246,4 @@ private static String join(final Iterable<?> iterable, final String sep) {
273246
}
274247
return buf.toString();
275248
}
276-
277-
/**
278-
* Validate XML without external schema.
279-
* @param xml XML Document
280-
* @param validator XML Validator
281-
* @return List of validation errors
282-
*/
283-
private static Collection<SAXParseException> validate(
284-
final XML xml,
285-
final Validator validator
286-
) {
287-
final Collection<SAXParseException> errors =
288-
new CopyOnWriteArrayList<>();
289-
final int max = 3;
290-
try {
291-
validator.setErrorHandler(
292-
new XMLDocument.ValidationHandler(errors)
293-
);
294-
final DOMSource dom = new DOMSource(xml.inner());
295-
for (int retry = 1; retry <= max; ++retry) {
296-
try {
297-
validator.validate(dom);
298-
break;
299-
} catch (final SocketException ex) {
300-
Logger.error(
301-
StrictXML.class,
302-
"Try #%d of %d failed: %s: %s",
303-
retry,
304-
max,
305-
ex.getClass().getName(),
306-
ex.getMessage()
307-
);
308-
if (retry == max) {
309-
throw new IllegalStateException(ex);
310-
}
311-
}
312-
}
313-
} catch (final SAXException | IOException ex) {
314-
throw new IllegalStateException(ex);
315-
}
316-
return errors;
317-
}
318-
319-
/**
320-
* Creates a new validator.
321-
* @param resolver The resolver for resources
322-
* @return A new validator
323-
*/
324-
private static Validator newValidator(final LSResourceResolver resolver) {
325-
try {
326-
final Validator validator = SchemaFactory
327-
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
328-
.newSchema()
329-
.newValidator();
330-
validator.setResourceResolver(resolver);
331-
return validator;
332-
} catch (final SAXException ex) {
333-
throw new IllegalStateException(ex);
334-
}
335-
}
336249
}

src/main/java/com/jcabi/xml/XML.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.List;
3434
import javax.xml.namespace.NamespaceContext;
3535
import org.w3c.dom.Node;
36+
import org.w3c.dom.ls.LSResourceResolver;
3637
import org.xml.sax.SAXParseException;
3738

3839
/**
@@ -185,10 +186,11 @@ public interface XML {
185186

186187
/**
187188
* Validate this XML against the XSD schema inside it.
189+
* @param resolver XSD schema resolver
188190
* @return List of errors found
189191
* @since 0.31.0
190192
*/
191-
Collection<SAXParseException> validate();
193+
Collection<SAXParseException> validate(LSResourceResolver resolver);
192194

193195
/**
194196
* Validate this XML against the provided XSD schema.
@@ -197,5 +199,4 @@ public interface XML {
197199
* @since 0.31.0
198200
*/
199201
Collection<SAXParseException> validate(XML xsd);
200-
201202
}

src/main/java/com/jcabi/xml/XMLDocument.java

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
import javax.xml.transform.dom.DOMSource;
6262
import javax.xml.transform.stream.StreamResult;
6363
import javax.xml.transform.stream.StreamSource;
64-
import javax.xml.validation.Schema;
6564
import javax.xml.validation.SchemaFactory;
6665
import javax.xml.validation.Validator;
6766
import javax.xml.xpath.XPath;
@@ -72,6 +71,7 @@
7271
import org.w3c.dom.Document;
7372
import org.w3c.dom.Node;
7473
import org.w3c.dom.NodeList;
74+
import org.w3c.dom.ls.LSResourceResolver;
7575
import org.xml.sax.ErrorHandler;
7676
import org.xml.sax.SAXException;
7777
import org.xml.sax.SAXParseException;
@@ -425,45 +425,51 @@ public XML merge(final NamespaceContext ctx) {
425425

426426
@Override
427427
public Collection<SAXParseException> validate(final XML xsd) {
428-
final Schema schema;
429-
try {
430-
schema = SchemaFactory
431-
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
432-
.newSchema(new StreamSource(new StringReader(xsd.toString())));
433-
} catch (final SAXException ex) {
434-
throw new IllegalStateException(
435-
String.format("Failed to create XSD schema from %s", xsd),
436-
ex
437-
);
428+
synchronized (xsd) {
429+
final Validator validator;
430+
try {
431+
validator = SchemaFactory
432+
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
433+
.newSchema(new StreamSource(new StringReader(xsd.toString())))
434+
.newValidator();
435+
} catch (final SAXException ex) {
436+
throw new IllegalStateException(
437+
String.format("Failed to create XSD schema from %s", xsd),
438+
ex
439+
);
440+
}
441+
return this.validate(validator);
438442
}
439-
return this.validate(schema);
440443
}
441444

442445
@Override
443-
public Collection<SAXParseException> validate() {
444-
final Schema schema;
445-
try {
446-
schema = SchemaFactory
447-
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
448-
.newSchema();
449-
} catch (final SAXException ex) {
450-
throw new IllegalStateException(
451-
"Failed to create XSD schema",
452-
ex
453-
);
446+
public Collection<SAXParseException> validate(final LSResourceResolver resolver) {
447+
synchronized (resolver) {
448+
final Validator validator;
449+
try {
450+
validator = SchemaFactory
451+
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
452+
.newSchema()
453+
.newValidator();
454+
validator.setResourceResolver(resolver);
455+
} catch (final SAXException ex) {
456+
throw new IllegalStateException(
457+
"Failed to create XSD schema",
458+
ex
459+
);
460+
}
461+
return this.validate(validator);
454462
}
455-
return this.validate(schema);
456463
}
457464

458465
/**
459-
* Validate against schema.
460-
* @param schema The XSD schema
466+
* Validate through validator.
467+
* @param validator Validator
461468
* @return List of errors
462469
*/
463-
public Collection<SAXParseException> validate(final Schema schema) {
470+
private Collection<SAXParseException> validate(final Validator validator) {
464471
final Collection<SAXParseException> errors =
465472
new CopyOnWriteArrayList<>();
466-
final Validator validator = schema.newValidator();
467473
validator.setErrorHandler(new XMLDocument.ValidationHandler(errors));
468474
try {
469475
validator.validate(new DOMSource(this.cache));
@@ -473,7 +479,7 @@ public Collection<SAXParseException> validate(final Schema schema) {
473479
if (Logger.isDebugEnabled(this)) {
474480
Logger.debug(
475481
this, "%s detected %d error(s)",
476-
schema.getClass().getName(), errors.size()
482+
validator.getClass().getName(), errors.size()
477483
);
478484
}
479485
return errors;
@@ -536,7 +542,9 @@ private <T> T fetch(final String query, final Class<T> type) throws XPathExpress
536542
)
537543
);
538544
}
539-
return (T) xpath.evaluate(query, this.cache, qname);
545+
synchronized (this.cache) {
546+
return (T) xpath.evaluate(query, this.cache, qname);
547+
}
540548
}
541549

542550
/**

0 commit comments

Comments
 (0)