diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/CompleteMultipartUploadRequestUnmarshaller.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/CompleteMultipartUploadRequestUnmarshaller.java index 17f7f575a6ca..cdaaa228ecd7 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/CompleteMultipartUploadRequestUnmarshaller.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/CompleteMultipartUploadRequestUnmarshaller.java @@ -44,14 +44,13 @@ public class CompleteMultipartUploadRequestUnmarshaller implements MessageBodyReader { private final JAXBContext context; - private final XMLReader xmlReader; + private final SAXParserFactory saxParserFactory; public CompleteMultipartUploadRequestUnmarshaller() { try { context = JAXBContext.newInstance(CompleteMultipartUploadRequest.class); - SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + saxParserFactory = SAXParserFactory.newInstance(); saxParserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - xmlReader = saxParserFactory.newSAXParser().getXMLReader(); } catch (Exception ex) { throw new AssertionError("Can not instantiate " + "CompleteMultipartUploadRequest parser", ex); @@ -70,6 +69,7 @@ public CompleteMultipartUploadRequest readFrom( MultivaluedMap multivaluedMap, InputStream inputStream) throws IOException, WebApplicationException { try { + XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader(); UnmarshallerHandler unmarshallerHandler = context.createUnmarshaller().getUnmarshallerHandler(); XmlNamespaceFilter filter = diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/MultiDeleteRequestUnmarshaller.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/MultiDeleteRequestUnmarshaller.java index f5745a8fc102..0c34c08091aa 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/MultiDeleteRequestUnmarshaller.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/MultiDeleteRequestUnmarshaller.java @@ -43,14 +43,13 @@ public class MultiDeleteRequestUnmarshaller implements MessageBodyReader { private final JAXBContext context; - private final XMLReader xmlReader; + private final SAXParserFactory saxParserFactory; public MultiDeleteRequestUnmarshaller() { try { context = JAXBContext.newInstance(MultiDeleteRequest.class); - SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + saxParserFactory = SAXParserFactory.newInstance(); saxParserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - xmlReader = saxParserFactory.newSAXParser().getXMLReader(); } catch (Exception ex) { throw new AssertionError("Can't instantiate MultiDeleteRequest parser", ex); @@ -68,6 +67,7 @@ public MultiDeleteRequest readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) { try { + XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader(); UnmarshallerHandler unmarshallerHandler = context.createUnmarshaller().getUnmarshallerHandler(); diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketAclRequestUnmarshaller.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketAclRequestUnmarshaller.java index 3ca2e47c469e..3fa6149815ea 100644 --- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketAclRequestUnmarshaller.java +++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketAclRequestUnmarshaller.java @@ -44,14 +44,13 @@ public class PutBucketAclRequestUnmarshaller implements MessageBodyReader { private final JAXBContext context; - private final XMLReader xmlReader; + private final SAXParserFactory saxParserFactory; public PutBucketAclRequestUnmarshaller() { try { context = JAXBContext.newInstance(S3BucketAcl.class); - SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + saxParserFactory = SAXParserFactory.newInstance(); saxParserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - xmlReader = saxParserFactory.newSAXParser().getXMLReader(); } catch (Exception ex) { throw new AssertionError("Can not instantiate " + "PutBucketAclRequest parser", ex); @@ -70,6 +69,7 @@ public S3BucketAcl readFrom( MultivaluedMap multivaluedMap, InputStream inputStream) throws IOException, WebApplicationException { try { + XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader(); UnmarshallerHandler unmarshallerHandler = context.createUnmarshaller().getUnmarshallerHandler(); XmlNamespaceFilter filter = diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestCompleteMultipartUploadRequestUnmarshaller.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestCompleteMultipartUploadRequestUnmarshaller.java index cd0fbfed4e65..1872c440da31 100644 --- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestCompleteMultipartUploadRequestUnmarshaller.java +++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestCompleteMultipartUploadRequestUnmarshaller.java @@ -20,12 +20,16 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.UUID; +import java.util.concurrent.CompletableFuture; + import org.junit.jupiter.api.Test; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** * Class tests Unmarshall logic of {@link CompleteMultipartUploadRequest}. @@ -75,6 +79,7 @@ public void fromStreamWithoutNamespace() throws IOException { } private void checkContent(CompleteMultipartUploadRequest request) { + assertNotNull(request); assertEquals(2, request.getPartList().size()); List parts = @@ -89,4 +94,43 @@ private CompleteMultipartUploadRequest unmarshall( return new CompleteMultipartUploadRequestUnmarshaller() .readFrom(null, null, null, null, null, inputBody); } + + @Test + public void concurrentParse() { + CompleteMultipartUploadRequestUnmarshaller unmarshaller = + new CompleteMultipartUploadRequestUnmarshaller(); + byte[] bytes = ("" + "" + part1 + + "1" + + part2 + "2" + + "").getBytes( + UTF_8); + + List> futures = + new ArrayList<>(); + for (int i = 0; i < 40; i++) { + futures.add(CompletableFuture.supplyAsync(() -> { + try { + //GIVEN + ByteArrayInputStream inputBody = new ByteArrayInputStream(bytes); + //WHEN + return unmarshall(unmarshaller, inputBody); + } catch (IOException e) { + return null; + } + })); + } + + for (CompletableFuture future : futures) { + CompleteMultipartUploadRequest request = future.join(); + //THEN + checkContent(request); + } + } + + private CompleteMultipartUploadRequest unmarshall( + CompleteMultipartUploadRequestUnmarshaller unmarshaller, + ByteArrayInputStream inputBody) throws IOException { + return unmarshaller + .readFrom(null, null, null, null, null, inputBody); + } }