This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 8a18bdb0a6bd CAMEL-25359: camel-barcode - return the hint maps as
read-only views (#27586)
8a18bdb0a6bd is described below
commit 8a18bdb0a6bd1c94d9fbe1be08cd9ae682be85f9
Author: allthingssecurity <[email protected]>
AuthorDate: Sat Oct 10 01:20:54 2026 +0530
CAMEL-25359: camel-barcode - return the hint maps as read-only views
(#27586)
getWriterHintMap() and getReaderHintMap() returned the live hint maps, so a
hint put into or removed from them was lost when the data format (re)started
and recomputed its hints. They now return read-only live views, so such a
change fails with UnsupportedOperationException instead of being lost, and
addToHintMap/removeFromHintMap are documented as the way to change the
hints.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../camel/catalog/docs/barcode-dataformat.adoc | 8 ++-
.../src/main/docs/barcode-dataformat.adoc | 8 ++-
.../dataformat/barcode/BarcodeDataFormat.java | 22 ++++++--
.../dataformat/barcode/BarcodeDataFormatTest.java | 65 ++++++++++++++++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 6 ++
5 files changed, 99 insertions(+), 10 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
index 0e6798e72d1a..5dd023395359 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
@@ -66,17 +66,19 @@ The default values are:
DataFormat code = new BarcodeDataFormat();
----
-If you want to use zxing hints, you can use the 'addToHintMap' method of
+If you want to use ZXing hints, you can use the 'addToHintMap' method of
your BarcodeDataFormat instance:
._Java-only: Java data format configuration API_
[source,java]
----
-code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.true);
+code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.TRUE);
----
The hints can be added before the data format is started (for example when the
route is configured).
-For possible hints, please consult the xzing documentation.
+To remove a hint, such as a default one, use the 'removeFromHintMap' method.
+The maps returned by 'getWriterHintMap' and 'getReaderHintMap' are read-only.
+For possible hints, please consult the ZXing documentation.
=== Marshalling
diff --git a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc
b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc
index 0e6798e72d1a..5dd023395359 100644
--- a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc
+++ b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc
@@ -66,17 +66,19 @@ The default values are:
DataFormat code = new BarcodeDataFormat();
----
-If you want to use zxing hints, you can use the 'addToHintMap' method of
+If you want to use ZXing hints, you can use the 'addToHintMap' method of
your BarcodeDataFormat instance:
._Java-only: Java data format configuration API_
[source,java]
----
-code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.true);
+code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.TRUE);
----
The hints can be added before the data format is started (for example when the
route is configured).
-For possible hints, please consult the xzing documentation.
+To remove a hint, such as a default one, use the 'removeFromHintMap' method.
+The maps returned by 'getWriterHintMap' and 'getReaderHintMap' are read-only.
+For possible hints, please consult the ZXing documentation.
=== Marshalling
diff --git
a/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
b/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
index 995cf47e6790..1ab95a87603f 100644
---
a/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
+++
b/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
@@ -19,6 +19,7 @@ package org.apache.camel.dataformat.barcode;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
@@ -80,6 +81,13 @@ public class BarcodeDataFormat extends ServiceSupport
implements DataFormat, Dat
*/
private final Map<DecodeHintType, Object> readerHintMap = new
EnumMap<>(DecodeHintType.class);
+ /**
+ * The read-only live views of the hint maps returned by the getters,
created once so that every call returns the
+ * same instance.
+ */
+ private final Map<EncodeHintType, Object> writerHintMapView =
Collections.unmodifiableMap(writerHintMap);
+ private final Map<DecodeHintType, Object> readerHintMapView =
Collections.unmodifiableMap(readerHintMap);
+
/**
* The hints added by the user, which are applied on top of the optimized
hints.
*/
@@ -313,17 +321,23 @@ public class BarcodeDataFormat extends ServiceSupport
implements DataFormat, Dat
}
/**
- * The writer (encode) hint map.
+ * The writer (encode) hint map, as a read-only live view: it shows the
later changes made with
+ * {@link #addToHintMap(EncodeHintType, Object)} and {@link
#removeFromHintMap(EncodeHintType)}, and the hints
+ * computed again when the data format starts or restarts. Use these
methods to change it, as only the changes made
+ * with them are applied again when the hints are computed again.
*/
public final Map<EncodeHintType, Object> getWriterHintMap() {
- return writerHintMap;
+ return writerHintMapView;
}
/**
- * The reader (decode) hint map.
+ * The reader (decode) hint map, as a read-only live view: it shows the
later changes made with
+ * {@link #addToHintMap(DecodeHintType, Object)} and {@link
#removeFromHintMap(DecodeHintType)}, and the hints
+ * computed again when the data format starts or restarts. Use these
methods to change it, as only the changes made
+ * with them are applied again when the hints are computed again.
*/
public final Map<DecodeHintType, Object> getReaderHintMap() {
- return readerHintMap;
+ return readerHintMapView;
}
public BarcodeFormat getBarcodeFormat() {
diff --git
a/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
b/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
index 870ac12961b8..e1b890a30ed7 100644
---
a/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
+++
b/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
@@ -22,11 +22,14 @@ import java.util.Map;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
@@ -229,6 +232,68 @@ public class BarcodeDataFormatTest {
}
}
+ /**
+ * A change made through the maps returned by the getters would bypass the
hints tracked by
+ * {@code addToHintMap}/{@code removeFromHintMap}, and be lost when the
data format starts again, so the maps are
+ * read-only.
+ */
+ @Test
+ final void testHintMapsAreReadOnly() throws IOException {
+ try (BarcodeDataFormat instance = new BarcodeDataFormat()) {
+ instance.start();
+ Map<EncodeHintType, Object> writerHints =
instance.getWriterHintMap();
+ Map<DecodeHintType, Object> readerHints =
instance.getReaderHintMap();
+
+ assertThrows(UnsupportedOperationException.class, () ->
writerHints.put(EncodeHintType.MARGIN, 10));
+ assertThrows(UnsupportedOperationException.class, () ->
writerHints.remove(EncodeHintType.ERROR_CORRECTION));
+ assertThrows(UnsupportedOperationException.class,
writerHints::clear);
+ assertThrows(UnsupportedOperationException.class, () ->
readerHints.put(DecodeHintType.PURE_BARCODE, true));
+ assertThrows(UnsupportedOperationException.class, () ->
readerHints.remove(DecodeHintType.TRY_HARDER));
+ assertThrows(UnsupportedOperationException.class,
readerHints::clear);
+
+ assertEquals(Map.of(EncodeHintType.ERROR_CORRECTION,
ErrorCorrectionLevel.H), instance.getWriterHintMap());
+ assertEquals(Map.of(DecodeHintType.TRY_HARDER, Boolean.TRUE),
instance.getReaderHintMap());
+ }
+ }
+
+ /**
+ * The maps returned by the getters are live views: a map obtained before
a change shows it afterwards, including
+ * the hints computed again when the data format starts and restarts.
+ */
+ @Test
+ final void testHintMapsAreLiveViews() throws IOException {
+ try (BarcodeDataFormat instance = new BarcodeDataFormat()) {
+ Map<EncodeHintType, Object> writerHints =
instance.getWriterHintMap();
+ Map<DecodeHintType, Object> readerHints =
instance.getReaderHintMap();
+
+ instance.addToHintMap(EncodeHintType.MARGIN, 5);
+ instance.addToHintMap(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
+ assertEquals(Map.of(EncodeHintType.MARGIN, 5), writerHints);
+ assertEquals(Map.of(DecodeHintType.PURE_BARCODE, Boolean.TRUE),
readerHints);
+
+ instance.start();
+ assertEquals(Map.of(EncodeHintType.ERROR_CORRECTION,
ErrorCorrectionLevel.H, EncodeHintType.MARGIN, 5),
+ writerHints);
+ assertEquals(Map.of(DecodeHintType.TRY_HARDER, Boolean.TRUE,
DecodeHintType.PURE_BARCODE, Boolean.TRUE),
+ readerHints);
+
+ instance.removeFromHintMap(EncodeHintType.ERROR_CORRECTION);
+ instance.removeFromHintMap(DecodeHintType.TRY_HARDER);
+ assertEquals(Map.of(EncodeHintType.MARGIN, 5), writerHints);
+ assertEquals(Map.of(DecodeHintType.PURE_BARCODE, Boolean.TRUE),
readerHints);
+
+ instance.stop();
+ instance.addToHintMap(EncodeHintType.MARGIN, 7);
+ instance.start();
+ assertEquals(Map.of(EncodeHintType.MARGIN, 7), writerHints);
+ assertEquals(Map.of(DecodeHintType.PURE_BARCODE, Boolean.TRUE),
readerHints);
+
+ // every call returns the same view
+ assertSame(writerHints, instance.getWriterHintMap());
+ assertSame(readerHints, instance.getReaderHintMap());
+ }
+ }
+
/**
* Helper to check the saved parameters.
*/
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 6cb1f2aad4a6..5fc3dada618f 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -960,6 +960,12 @@ instead of the `?` characters, so it must decode them as
UTF-8. Text that ISO-88
before, byte for byte, and a `CHARACTER_SET` hint takes precedence. The
documented default encoding is now
"ISO-8859-1, or UTF-8 when needed" instead of "UTF-8".
+=== camel-barcode - the hint maps are read-only (Breaking change)
+
+The maps returned by `BarcodeDataFormat.getWriterHintMap()` and
`getReaderHintMap()` are now read-only views, so
+changing them throws an `UnsupportedOperationException`. Such changes were
lost when the data format started (again),
+since the hints are computed at start. Use `addToHintMap` and
`removeFromHintMap` instead.
+
=== camel-bindy - fixed-length records with characters outside the BMP
Since Camel 3.1 a fixed-length record is read by counting code points (or
graphemes with