This is an automated email from the ASF dual-hosted git repository.
ChenSammi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new e62ad5b37af HDDS-16248. Refactor
PutBucketLifecycleConfigurationUnmarshaller to extend MessageUnmarshaller
(#11075)
e62ad5b37af is described below
commit e62ad5b37afca7ac2baef2489f15aa9674ce76a6
Author: Sammi Chen <[email protected]>
AuthorDate: Tue Aug 25 16:32:59 2026 +0800
HDDS-16248. Refactor PutBucketLifecycleConfigurationUnmarshaller to extend
MessageUnmarshaller (#11075)
---
.../ozone/s3/endpoint/BucketLifecycleHandler.java | 3 +-
...utBucketLifecycleConfigurationUnmarshaller.java | 56 +-------------
...utBucketLifecycleConfigurationUnmarshaller.java | 86 ++++++++++++++++++++++
3 files changed, 90 insertions(+), 55 deletions(-)
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
index cf4270f925b..f25ea9d8b89 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketLifecycleHandler.java
@@ -133,8 +133,7 @@ public Response
putBucketLifecycleConfiguration(S3RequestContext context, String
OzoneBucket ozoneBucket = context.getVolume().getBucket(bucketName);
OmLifecycleConfiguration lcc;
try {
- s3LifecycleConfiguration = new
PutBucketLifecycleConfigurationUnmarshaller().readFrom(null,
- null, null, null, null, body);
+ s3LifecycleConfiguration = new
PutBucketLifecycleConfigurationUnmarshaller().readFrom(body);
lcc = s3LifecycleConfiguration.toOmLifecycleConfiguration(ozoneBucket);
} catch (WebApplicationException ex) {
throw S3ErrorTable.newError(S3ErrorTable.MALFORMED_XML, bucketName);
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketLifecycleConfigurationUnmarshaller.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketLifecycleConfigurationUnmarshaller.java
index 6cf28a7c12f..36da3bde2de 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketLifecycleConfigurationUnmarshaller.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/PutBucketLifecycleConfigurationUnmarshaller.java
@@ -17,64 +17,14 @@
package org.apache.hadoop.ozone.s3.endpoint;
-import static org.apache.hadoop.ozone.s3.util.S3Consts.S3_XML_NAMESPACE;
-
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.xml.XMLConstants;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.UnmarshallerHandler;
-import javax.xml.parsers.SAXParserFactory;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-
/**
- * Custom unmarshaller to read Lifecycle configuration namespace.
+ * Custom unmarshaller to read Lifecycle configuration.
*/
public class PutBucketLifecycleConfigurationUnmarshaller
- implements MessageBodyReader<S3LifecycleConfiguration> {
-
- private final JAXBContext context;
- private final XMLReader xmlReader;
+ extends MessageUnmarshaller<S3LifecycleConfiguration> {
public PutBucketLifecycleConfigurationUnmarshaller() {
- try {
- context = JAXBContext.newInstance(S3LifecycleConfiguration.class);
- SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
- saxParserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,
true);
- xmlReader = saxParserFactory.newSAXParser().getXMLReader();
- } catch (Exception ex) {
- throw new AssertionError("Can not instantiate " +
- "PutBucketLifecycleConfiguration parser", ex);
- }
+ super(S3LifecycleConfiguration.class);
}
- @Override
- public boolean isReadable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return type.equals(S3LifecycleConfiguration.class);
- }
-
- @Override
- public S3LifecycleConfiguration readFrom(Class<S3LifecycleConfiguration>
type,
- Type genericType, Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream inputStream)
- throws WebApplicationException {
- try {
- UnmarshallerHandler unmarshallerHandler =
- context.createUnmarshaller().getUnmarshallerHandler();
- XmlNamespaceFilter filter = new XmlNamespaceFilter(S3_XML_NAMESPACE);
- filter.setContentHandler(unmarshallerHandler);
- filter.setParent(xmlReader);
- filter.parse(new InputSource(inputStream));
- return (S3LifecycleConfiguration)(unmarshallerHandler.getResult());
- } catch (Exception e) {
- throw new WebApplicationException("Can't parse request body to XML.", e);
- }
- }
}
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPutBucketLifecycleConfigurationUnmarshaller.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPutBucketLifecycleConfigurationUnmarshaller.java
new file mode 100644
index 00000000000..76c67c5e3da
--- /dev/null
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPutBucketLifecycleConfigurationUnmarshaller.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.s3.endpoint;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import javax.ws.rs.WebApplicationException;
+import org.apache.hadoop.ozone.s3.util.S3Consts;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests XML parsing for {@link PutBucketLifecycleConfigurationUnmarshaller}.
+ */
+public class TestPutBucketLifecycleConfigurationUnmarshaller {
+
+ @Test
+ public void fromStreamWithNamespace() {
+ ByteArrayInputStream inputBody = new ByteArrayInputStream(
+ ("<LifecycleConfiguration xmlns=\"" + S3Consts.S3_XML_NAMESPACE +
"\">" +
+ "<Rule>" +
+ "<ID>expire after 1 day</ID>" +
+ "<Status>Enabled</Status>" +
+ "<Expiration><Days>1</Days></Expiration>" +
+ "</Rule>" +
+ "</LifecycleConfiguration>")
+ .getBytes(UTF_8));
+
+ S3LifecycleConfiguration configuration =
+ new PutBucketLifecycleConfigurationUnmarshaller().readFrom(inputBody);
+
+ assertNotNull(configuration);
+ assertEquals(1, configuration.getRules().size());
+ assertEquals("expire after 1 day",
configuration.getRules().get(0).getId());
+ }
+
+ @Test
+ public void lifecycleXmlWithDoctypeIsRejected() {
+ String xml = "<?xml version=\"1.0\"?>\n"
+ + "<!DOCTYPE LifecycleConfiguration ["
+ + "<!ENTITY xxe SYSTEM \"file:///etc/passwd\">]>\n"
+ + "<LifecycleConfiguration xmlns=\"" + S3Consts.S3_XML_NAMESPACE +
"\">"
+ + "<Rule>"
+ + "<ID>rule1</ID>"
+ + "<Status>Enabled</Status>"
+ + "<Expiration><Days>1</Days></Expiration>"
+ + "</Rule>"
+ + "</LifecycleConfiguration>";
+
+ WebApplicationException ex = assertThrows(WebApplicationException.class,
+ () -> new PutBucketLifecycleConfigurationUnmarshaller()
+ .readFrom(new ByteArrayInputStream(xml.getBytes(UTF_8))));
+
+ assertTrue(containsDisallowDoctypeDecl(ex),
+ "Expected parser to reject DOCTYPE declarations");
+ }
+
+ private static boolean containsDisallowDoctypeDecl(Throwable throwable) {
+ for (Throwable current = throwable; current != null; current =
current.getCause()) {
+ if (current.getMessage() != null
+ && current.getMessage().contains("disallow-doctype-decl")) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]