From 45e8dee8210b5f64699564586702cff4e64012f5 Mon Sep 17 00:00:00 2001 From: Fritz Schinkel Date: Thu, 21 Dec 2023 15:45:45 +0100 Subject: [PATCH] Sign IIds Add IIdCodecFlag to parametrize IdCodec-calls. The IdCodec will add a signature to the unqualified ids during serialization and asserts the signature's validity during deserialization. Add annotation IdSignature which can be used to exclude IIds from signature creation during serialization/deserialization in the IdCodec. Pass ScoutDataObjectModuleContext to all IId-serializers/deserializers and use it to compute the IIdCodecFlags for each call to IdCodec. Add IIdSignatureDataObjectMapper/JacksonIdSignatureDataObjectMapper that uses signatures during serializing/deserializing and use it in JSON layer. Add rest.jersey.server-module to inject reader/writer that uses signatures and IIdCodecFlags to param converters. Add IdSignatureRestClientFilter to inject writer/reader that uses signatures. 340299, 373060 --- .../dataobject/fixture/FixtureIntegerId.java | 2 + .../rt/dataobject/id/AbstractIdCodecTest.java | 132 +++++- .../scout/rt/dataobject/id/IdCodecTest.java | 8 +- .../rt/dataobject/id/IdInventoryTest.java | 127 +++++- ...CompositeIdDataObjectVisitorExtension.java | 5 +- .../IIdSignatureDataObjectMapper.java | 20 + .../rt/dataobject/id/AbstractCompositeId.java | 1 + .../rt/dataobject/id/AbstractStringId.java | 4 + .../scout/rt/dataobject/id/AbstractUuId.java | 5 +- .../eclipse/scout/rt/dataobject/id/IId.java | 1 + .../scout/rt/dataobject/id/IdCodec.java | 235 +++++++++-- .../scout/rt/dataobject/id/IdInventory.java | 55 ++- .../scout/rt/dataobject/id/IdSignature.java | 33 ++ .../scout/rt/dataobject/id/IdTypeName.java | 8 +- .../id/QualifiedIIdSerializationTest.java | 6 +- .../JacksonIdSignatureDataObjectMapper.java | 31 ++ .../ScoutDataObjectModuleContext.java | 15 +- .../ScoutDataObjectSerializerProvider.java | 14 +- .../id/AbstractIdCodecDeserializer.java | 61 +++ .../id/AbstractIdCodecMapKeyDeserializer.java | 53 +++ .../id/AbstractIdCodecMapKeySerializer.java | 53 +++ .../id/AbstractIdCodecSerializer.java | 61 +++ .../jackson/dataobject/id/IdCodecUtility.java | 42 ++ .../id/QualifiedIIdDeserializer.java | 25 +- .../id/QualifiedIIdMapKeyDeserializer.java | 22 +- .../id/QualifiedIIdMapKeySerializer.java | 13 +- .../dataobject/id/QualifiedIIdSerializer.java | 15 +- .../dataobject/id/TypedIdDeserializer.java | 18 +- .../dataobject/id/TypedIdSerializer.java | 16 +- .../id/UnqualifiedIIdDeserializer.java | 15 +- .../id/UnqualifiedIIdMapKeyDeserializer.java | 14 +- .../id/UnqualifiedIIdMapKeySerializer.java | 14 +- .../id/UnqualifiedIIdSerializer.java | 16 +- .../pom.xml | 10 +- .../client/IdSignatureRestClientFilter.java | 111 +++++ .../org.eclipse.core.resources.prefs | 18 + .../.settings/org.eclipse.core.runtime.prefs | 2 + .../.settings/org.eclipse.jdt.apt.core.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 399 ++++++++++++++++++ .../.settings/org.eclipse.jdt.launching.prefs | 2 + .../.settings/org.eclipse.jdt.ui.prefs | 127 ++++++ .../.settings/org.eclipse.m2e.core.prefs | 4 + .../pom.xml | 39 ++ .../IdSignatureRestContainerFilter.java | 163 +++++++ .../src/main/resources/META-INF/scout.xml | 12 + org.eclipse.scout.rt.rest.jersey.test/pom.xml | 14 +- .../rt/rest/jersey/JerseyTestApplication.java | 14 +- .../jersey/fixture/SerializationRequest.java | 40 ++ .../jersey/fixture/SerializationResource.java | 31 ++ .../jersey/fixture/SerializationResponse.java | 55 +++ .../rt/rest/jersey/fixture/SingleIdDo.java | 40 ++ .../client/AbstractRestClientHelperTest.java | 4 +- .../server/IdSignatureRestFilterTest.java | 133 ++++++ .../param/IIdParamConverterProviderTest.java | 58 ++- org.eclipse.scout.rt.rest/pom.xml | 7 +- .../rest/client/AbstractRestClientHelper.java | 18 +- .../client/IGlobalRestResponseFilter.java | 24 ++ .../rest/param/IIdParamConverterProvider.java | 78 +++- ...ignatureHttpServletRequestWrapperTest.java | 134 ++++++ .../server/commons/id/IdSignatureFilter.java | 82 ++++ .../mapping/AbstractCodeToDoFunction.java | 3 +- .../rt/ui/html/json/JsonDataObjectHelper.java | 16 +- org.eclipse.scout.rt/pom.xml | 14 + 63 files changed, 2581 insertions(+), 213 deletions(-) create mode 100644 org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/IIdSignatureDataObjectMapper.java create mode 100644 org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdSignature.java create mode 100644 org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/JacksonIdSignatureDataObjectMapper.java create mode 100644 org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecDeserializer.java create mode 100644 org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeyDeserializer.java create mode 100644 org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeySerializer.java create mode 100644 org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecSerializer.java create mode 100644 org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/IdCodecUtility.java create mode 100644 org.eclipse.scout.rt.rest.jersey.client/src/main/java/org/eclipse/scout/rt/rest/jersey/client/IdSignatureRestClientFilter.java create mode 100644 org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.resources.prefs create mode 100644 org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.runtime.prefs create mode 100644 org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.apt.core.prefs create mode 100644 org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.core.prefs create mode 100644 org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.launching.prefs create mode 100644 org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.ui.prefs create mode 100644 org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.m2e.core.prefs create mode 100644 org.eclipse.scout.rt.rest.jersey.server/pom.xml create mode 100644 org.eclipse.scout.rt.rest.jersey.server/src/main/java/org/eclipse/scout/rt/rest/jersey/server/IdSignatureRestContainerFilter.java create mode 100644 org.eclipse.scout.rt.rest.jersey.server/src/main/resources/META-INF/scout.xml create mode 100644 org.eclipse.scout.rt.rest.jersey.test/src/main/java/org/eclipse/scout/rt/rest/jersey/fixture/SerializationRequest.java create mode 100644 org.eclipse.scout.rt.rest.jersey.test/src/main/java/org/eclipse/scout/rt/rest/jersey/fixture/SerializationResource.java create mode 100644 org.eclipse.scout.rt.rest.jersey.test/src/main/java/org/eclipse/scout/rt/rest/jersey/fixture/SerializationResponse.java create mode 100644 org.eclipse.scout.rt.rest.jersey.test/src/main/java/org/eclipse/scout/rt/rest/jersey/fixture/SingleIdDo.java create mode 100644 org.eclipse.scout.rt.rest.jersey.test/src/test/java/org/eclipse/scout/rt/rest/jersey/server/IdSignatureRestFilterTest.java create mode 100644 org.eclipse.scout.rt.rest/src/main/java/org/eclipse/scout/rt/rest/client/IGlobalRestResponseFilter.java create mode 100644 org.eclipse.scout.rt.server.commons.test/src/test/java/org/eclipse/scout/rt/server/commons/id/SignatureHttpServletRequestWrapperTest.java create mode 100644 org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/id/IdSignatureFilter.java diff --git a/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/fixture/FixtureIntegerId.java b/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/fixture/FixtureIntegerId.java index ff8c11e500c..3e22a1286af 100644 --- a/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/fixture/FixtureIntegerId.java +++ b/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/fixture/FixtureIntegerId.java @@ -10,7 +10,9 @@ package org.eclipse.scout.rt.dataobject.fixture; import org.eclipse.scout.rt.dataobject.id.AbstractRootId; +import org.eclipse.scout.rt.dataobject.id.IdTypeName; +@IdTypeName("scout.FixtureIntegerId") public final class FixtureIntegerId extends AbstractRootId { private static final long serialVersionUID = 1L; diff --git a/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractIdCodecTest.java b/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractIdCodecTest.java index 9b01792f072..2ec2630fd50 100644 --- a/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractIdCodecTest.java +++ b/org.eclipse.scout.rt.dataobject.test/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractIdCodecTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -11,9 +11,12 @@ import static org.junit.Assert.*; +import java.nio.charset.StandardCharsets; import java.util.Date; +import java.util.HashSet; import java.util.Locale; import java.util.Objects; +import java.util.Set; import java.util.UUID; import org.eclipse.scout.rt.dataobject.fixture.FixtureCompositeId; @@ -22,11 +25,17 @@ import org.eclipse.scout.rt.dataobject.fixture.FixtureStringId; import org.eclipse.scout.rt.dataobject.fixture.FixtureUuId; import org.eclipse.scout.rt.dataobject.fixture.FixtureWrapperCompositeId; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IdCodecFlag; import org.eclipse.scout.rt.platform.BEANS; +import org.eclipse.scout.rt.platform.BeanMetaData; +import org.eclipse.scout.rt.platform.IBean; import org.eclipse.scout.rt.platform.exception.PlatformException; import org.eclipse.scout.rt.platform.util.Assertions.AssertionException; import org.eclipse.scout.rt.platform.util.StringUtility; import org.eclipse.scout.rt.platform.util.date.IDateProvider; +import org.eclipse.scout.rt.testing.platform.BeanTestingHelper; +import org.junit.After; +import org.junit.Before; import org.junit.Test; /** @@ -40,6 +49,22 @@ public abstract class AbstractIdCodecTest { protected static final String TEST_STRING_2 = "bazäöl"; protected static final Date TEST_DATE = new Date(123456789); + protected IBean m_codecBean; + + @Before + public void before() { + m_codecBean = BeanTestingHelper.get().registerBean(new BeanMetaData(getCodecReplacementType()).withReplace(true)); + } + + @After + public void after() { + BeanTestingHelper.get().unregisterBean(m_codecBean); + } + + protected Class getCodecReplacementType() { + return P_IdCodec.class; + } + /** * @return IdCodec instance used for tests */ @@ -571,13 +596,13 @@ public void testFromQualified_UnsupportedWrappedType() { @Test public void testFromQualifiedLenient_Default() { FixtureUuId id = FixtureUuId.of(TEST_UUID); - IId id2 = getCodec().fromQualifiedLenient("scout.FixtureUuId:" + TEST_UUID); + IId id2 = getCodec().fromQualified("scout.FixtureUuId:" + TEST_UUID, IdCodecFlag.LENIENT); assertEquals(id, id2); } @Test public void testFromQualifiedLenient_UnknownType() { - IId id = getCodec().fromQualifiedLenient("DoesNotExist:" + TEST_UUID); + IId id = getCodec().fromQualified("DoesNotExist:" + TEST_UUID, IdCodecFlag.LENIENT); assertTrue(id instanceof UnknownId); UnknownId uid = (UnknownId) id; assertEquals("DoesNotExist", uid.getIdTypeName()); @@ -589,7 +614,7 @@ public void testFromQualifiedLenient_UnknownType() { @Test public void testFromQualifiedLenient_CompositeUnknownType() { - IId id = getCodec().fromQualifiedLenient("DoesNotExist:abc;123"); + IId id = getCodec().fromQualified("DoesNotExist:abc;123", IdCodecFlag.LENIENT); assertTrue(id instanceof UnknownId); UnknownId uid = (UnknownId) id; assertEquals("DoesNotExist", uid.getIdTypeName()); @@ -601,7 +626,7 @@ public void testFromQualifiedLenient_CompositeUnknownType() { @Test public void testFromQualifiedLenient_WrongFormat() { - IId id = getCodec().fromQualifiedLenient("Does:Not:Exist:" + TEST_UUID); + IId id = getCodec().fromQualified("Does:Not:Exist:" + TEST_UUID, IdCodecFlag.LENIENT); assertTrue(id instanceof UnknownId); UnknownId uid = (UnknownId) id; assertEquals("Does", uid.getIdTypeName()); @@ -613,7 +638,7 @@ public void testFromQualifiedLenient_WrongFormat() { @Test public void testFromQualifiedLenient_NoIdTypeName() { - IId id = getCodec().fromQualifiedLenient("Foo" + TEST_UUID); + IId id = getCodec().fromQualified("Foo" + TEST_UUID, IdCodecFlag.LENIENT); assertTrue(id instanceof UnknownId); UnknownId uid = (UnknownId) id; assertNull(uid.getIdTypeName()); @@ -625,7 +650,7 @@ public void testFromQualifiedLenient_NoIdTypeName() { @Test public void testFromQualifiedLenient_CompositeWrongCardinalityToSmall() { - IId id = getCodec().fromQualifiedLenient("scout.FixtureCompositeId:" + TEST_UUID); + IId id = getCodec().fromQualified("scout.FixtureCompositeId:" + TEST_UUID, IdCodecFlag.LENIENT); assertTrue(id instanceof UnknownId); UnknownId uid = (UnknownId) id; assertEquals("scout.FixtureCompositeId", uid.getIdTypeName()); @@ -637,7 +662,7 @@ public void testFromQualifiedLenient_CompositeWrongCardinalityToSmall() { @Test public void testFromQualifiedLenient_CompositeWrongCardinalityToHigh() { - IId id = getCodec().fromQualifiedLenient("scout.FixtureCompositeId:" + "a;b;c"); + IId id = getCodec().fromQualified("scout.FixtureCompositeId:" + "a;b;c", IdCodecFlag.LENIENT); assertTrue(id instanceof UnknownId); UnknownId uid = (UnknownId) id; assertEquals("scout.FixtureCompositeId", uid.getIdTypeName()); @@ -654,6 +679,89 @@ public void testRegisterTypeMapper() { assertThrows(AssertionException.class, () -> getCodec().registerRawTypeMapper(String.class, x -> x, null)); } + @Test + public void testQualifiedSignature() { + var ids = new HashSet(); + collectSignatureIds(ids); + ids.forEach(id -> { + String serialized = getCodec().toQualified(id, IdCodecFlag.SIGNATURE); + IId deserialized = getCodec().fromQualified(serialized, IdCodecFlag.SIGNATURE); + assertQualifiedSignature(id, serialized, deserialized); + + serialized = getCodec().toQualified(id, Set.of(IdCodecFlag.SIGNATURE)); + deserialized = getCodec().fromQualified(serialized, Set.of(IdCodecFlag.SIGNATURE)); + assertQualifiedSignature(id, serialized, deserialized); + }); + } + + @Test + public void testUnqualifiedSignature() { + var ids = new HashSet(); + collectSignatureIds(ids); + ids.forEach(id -> { + String serialized = getCodec().toUnqualified(id, IdCodecFlag.SIGNATURE); + IId deserialized = getCodec().fromUnqualified(id.getClass(), serialized, IdCodecFlag.SIGNATURE); + assertUnqualifiedSignature(id, serialized, deserialized); + + serialized = getCodec().toUnqualified(id, Set.of(IdCodecFlag.SIGNATURE)); + deserialized = getCodec().fromUnqualified(id.getClass(), serialized, Set.of(IdCodecFlag.SIGNATURE)); + assertUnqualifiedSignature(id, serialized, deserialized); + }); + } + + protected void assertQualifiedSignature(IId id, String serialized, IId deserialized) { + assertSignature(id, serialized, deserialized); + } + + protected void assertUnqualifiedSignature(IId id, String serialized, IId deserialized) { + assertSignature(id, serialized, deserialized); + } + + protected void assertSignature(IId id, String serialized, IId deserialized) { + assertEquals(id, deserialized); + } + + protected void collectSignatureIds(Set ids) { + ids.add(FixtureUuId.of(TEST_UUID)); + ids.add(FixtureStringId.of(TEST_STRING)); + ids.add(FixtureDateId.of(TEST_DATE)); + ids.add(FixtureLocaleId.of(Locale.ITALY)); + ids.add(FixtureCompositeId.of(TEST_STRING, TEST_UUID)); + ids.add(FixtureWrapperCompositeId.of(TEST_STRING, TEST_UUID, TEST_STRING_2)); + ids.add(FixtureCompositeWithNullValuesId.of(null, UUID.fromString("711dc5d6-0a42-4f54-b79c-50110b9e742a"))); + ids.add(FixtureCompositeWithNullStringValuesId.of("foo", "")); + ids.add(FixtureCompositeWithNullStringValuesId.of("", "bar")); + ids.add(FixtureCompositeWithAllTypesId.of("foo", null, null, null, null, null)); + ids.add(FixtureCompositeWithAllTypesId.of(null, TEST_UUID, null, null, null, null)); + ids.add(FixtureCompositeWithAllTypesId.of(null, null, 42L, null, null, null)); + ids.add(FixtureCompositeWithAllTypesId.of(null, null, null, 43, null, null)); + ids.add(FixtureCompositeWithAllTypesId.of(null, null, null, null, TEST_DATE, null)); + ids.add(FixtureCompositeWithAllTypesId.of(null, null, null, null, null, Locale.GERMANY)); + } + + @Test + public void testEmptyIdWithSignature() { + assertThrows(AssertionException.class, () -> getCodec().fromQualified("scout.FixtureIntegerId:###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE)); + assertThrows(AssertionException.class, () -> getCodec().fromUnqualified(FixtureIntegerId.class, "###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE)); + } + + @Test + public void testSignatureIdWithoutPassword() { + BeanTestingHelper.get().unregisterBean(m_codecBean); + + var stringId = FixtureStringId.of("some"); + assertEquals("scout.FixtureStringId:some", getCodec().toQualified(stringId, IdCodecFlag.SIGNATURE)); + assertEquals("some", getCodec().toUnqualified(stringId, IdCodecFlag.SIGNATURE)); + assertEquals(stringId, getCodec().fromQualified("scout.FixtureStringId:some", IdCodecFlag.SIGNATURE)); + assertEquals(stringId, getCodec().fromUnqualified(FixtureStringId.class, "some", IdCodecFlag.SIGNATURE)); + + var integerId = FixtureIntegerId.of(42); + assertThrows(AssertionException.class, () -> getCodec().toQualified(integerId, IdCodecFlag.SIGNATURE)); + assertThrows(AssertionException.class, () -> getCodec().toUnqualified(integerId, IdCodecFlag.SIGNATURE)); + assertThrows(AssertionException.class, () -> getCodec().fromQualified("scout.FixtureIntegerId:42###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE)); + assertThrows(AssertionException.class, () -> getCodec().fromUnqualified(FixtureIntegerId.class, "42###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE)); + } + @IdTypeName("scout.FixtureDateId") protected static final class FixtureDateId extends AbstractRootId { private static final long serialVersionUID = 1L; @@ -812,4 +920,12 @@ public static FixtureCustomComparableRawDataId of(CustomComparableRawDataType da return new FixtureCustomComparableRawDataId(date); } } + + protected static class P_IdCodec extends IdCodec { + + @Override + protected byte[] getIdSignaturePassword() { + return "42".getBytes(StandardCharsets.UTF_8); + } + } } diff --git a/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdCodecTest.java b/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdCodecTest.java index eae34030d4f..e57f6277774 100644 --- a/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdCodecTest.java +++ b/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdCodecTest.java @@ -16,14 +16,8 @@ */ public class IdCodecTest extends AbstractIdCodecTest { - protected IdCodec m_idCodec; - - public IdCodecTest() { - m_idCodec = BEANS.get(IdCodec.class); - } - @Override protected IdCodec getCodec() { - return m_idCodec; + return BEANS.get(IdCodec.class); } } diff --git a/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdInventoryTest.java b/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdInventoryTest.java index f96bfc2bae7..5c48ec0b4e7 100644 --- a/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdInventoryTest.java +++ b/org.eclipse.scout.rt.dataobject.test/src/test/java/org/eclipse/scout/rt/dataobject/id/IdInventoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -59,6 +59,19 @@ public void testRegisterIdTypeName() { assertThrows(AssertionException.class, () -> m_inventory.registerIdTypeName("scout.FixtureMockId", FixtureMockId.class)); } + @Test + public void testIdSignature() { + assertTrue(m_inventory.isIdSignature(ExplicitlyOverriddenSignedId.class)); + assertTrue(m_inventory.isIdSignature(ImplicitlyOverriddenSignedId.class)); + assertTrue(m_inventory.isIdSignature(ExplicitlySignedId.class)); + assertTrue(m_inventory.isIdSignature(ImplicitlySignedId.class)); + + assertFalse(m_inventory.isIdSignature(ImplicitlyUnsignedId.class)); + assertFalse(m_inventory.isIdSignature(ExplicitlyUnsignedId.class)); + assertFalse(m_inventory.isIdSignature(ImplicitlyOverriddenUnsignedId.class)); + assertFalse(m_inventory.isIdSignature(ExplicitlyOverriddenUnsignedId.class)); + } + @IgnoreBean protected static final class FixtureMockId extends AbstractStringId { private static final long serialVersionUID = 1L; @@ -67,4 +80,116 @@ private FixtureMockId(String id) { super(id); } } + + @IdSignature + protected abstract static class AbstractImplicitlySignedId extends AbstractStringId { + private static final long serialVersionUID = 1L; + + protected AbstractImplicitlySignedId(String id) { + super(id); + } + } + + @IgnoreBean + protected static class ImplicitlySignedId extends AbstractImplicitlySignedId { + private static final long serialVersionUID = 1L; + + protected ImplicitlySignedId(String id) { + super(id); + } + } + + @IgnoreBean + @IdSignature + protected static class ExplicitlySignedId extends AbstractStringId { + private static final long serialVersionUID = 1L; + + protected ExplicitlySignedId(String id) { + super(id); + } + } + + @IdSignature(false) + protected abstract static class AbstractImplicitlyUnsignedId extends AbstractStringId { + private static final long serialVersionUID = 1L; + + protected AbstractImplicitlyUnsignedId(String id) { + super(id); + } + } + + @IgnoreBean + protected static class ImplicitlyUnsignedId extends AbstractImplicitlyUnsignedId { + private static final long serialVersionUID = 1L; + + protected ImplicitlyUnsignedId(String id) { + super(id); + } + } + + @IgnoreBean + @IdSignature(false) + protected static class ExplicitlyUnsignedId extends AbstractStringId { + private static final long serialVersionUID = 1L; + + protected ExplicitlyUnsignedId(String id) { + super(id); + } + } + + @IdSignature + protected abstract static class AbstractImplicitlyOverriddenSignedId extends AbstractImplicitlyUnsignedId { + private static final long serialVersionUID = 1L; + + protected AbstractImplicitlyOverriddenSignedId(String id) { + super(id); + } + } + + @IgnoreBean + protected static class ImplicitlyOverriddenSignedId extends AbstractImplicitlyOverriddenSignedId { + private static final long serialVersionUID = 1L; + + protected ImplicitlyOverriddenSignedId(String id) { + super(id); + } + } + + @IgnoreBean + @IdSignature + protected static class ExplicitlyOverriddenSignedId extends AbstractImplicitlyUnsignedId { + private static final long serialVersionUID = 1L; + + protected ExplicitlyOverriddenSignedId(String id) { + super(id); + } + } + + @IdSignature(false) + protected abstract static class AbstractImplicitlyOverriddenUnsignedId extends AbstractImplicitlySignedId { + private static final long serialVersionUID = 1L; + + protected AbstractImplicitlyOverriddenUnsignedId(String id) { + super(id); + } + } + + @IgnoreBean + protected static class ImplicitlyOverriddenUnsignedId extends AbstractImplicitlyOverriddenUnsignedId { + private static final long serialVersionUID = 1L; + + protected ImplicitlyOverriddenUnsignedId(String id) { + super(id); + } + } + + @IgnoreBean + @IdSignature(false) + protected static class ExplicitlyOverriddenUnsignedId extends AbstractImplicitlySignedId { + private static final long serialVersionUID = 1L; + + protected ExplicitlyOverriddenUnsignedId(String id) { + super(id); + } + } } diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/CompositeIdDataObjectVisitorExtension.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/CompositeIdDataObjectVisitorExtension.java index 49380d22750..accb8ccb4fa 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/CompositeIdDataObjectVisitorExtension.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/CompositeIdDataObjectVisitorExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -20,6 +20,7 @@ import org.eclipse.scout.rt.dataobject.id.IIds; import org.eclipse.scout.rt.dataobject.id.IRootId; import org.eclipse.scout.rt.dataobject.id.IdCodec; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IIdCodecFlag; import org.eclipse.scout.rt.platform.exception.PlatformException; /** @@ -50,7 +51,7 @@ public ICompositeId replaceOrVisit(ICompositeId value, UnaryOperator cha } /** - * Similar as in {@link IdCodec#toUnqualified(IId)}. + * Similar as in {@link IdCodec#toUnqualified(IId, IIdCodecFlag...)}. */ protected void unwrap(IId component, List unwrappedComponents) { if (component instanceof IRootId) { diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/IIdSignatureDataObjectMapper.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/IIdSignatureDataObjectMapper.java new file mode 100644 index 00000000000..50d55332c95 --- /dev/null +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/IIdSignatureDataObjectMapper.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.dataobject; + +import org.eclipse.scout.rt.dataobject.id.IId; + +/** + * Interface to a data mapper that uses signatures for all {@link IId} instances. + * + * @see IDataObjectMapper + */ +public interface IIdSignatureDataObjectMapper extends IDataObjectMapper { +} diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractCompositeId.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractCompositeId.java index 89e1e7c073c..1bfecb10b33 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractCompositeId.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractCompositeId.java @@ -18,6 +18,7 @@ * multiple {@link IId}'s as components. The type(s) of the raw (wrapped) ids is required to be an instance of * {@link IId}. */ +@IdSignature public abstract class AbstractCompositeId implements ICompositeId { private static final long serialVersionUID = 1L; diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractStringId.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractStringId.java index 0c155937926..f0463026d17 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractStringId.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractStringId.java @@ -13,8 +13,12 @@ * Abstract base implementation for all {@link String} based {@link IId} classes. The wrapped id is guaranteed to be * non-null. *

+ * Usually not used for transactional data ids which should be saved from being probed. Therefore, {@link IdSignature} + * is disabled. + *

* For details, see {@link IStringId}. */ +@IdSignature(false) public abstract class AbstractStringId extends AbstractRootId implements IStringId { private static final long serialVersionUID = 1L; diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractUuId.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractUuId.java index 8a5f53d3ac3..25e9781c75c 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractUuId.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/AbstractUuId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -15,8 +15,11 @@ * Abstract base implementation for all {@link UUID} based {@link IId} classes. The wrapped id is guaranteed to be * non-null. *

+ * Key probing is not relevant for ids using {@link UUID}. Therefore, {@link IdSignature} is disabled. + *

* For details, see {@link IUuId}. */ +@IdSignature(false) public abstract class AbstractUuId extends AbstractRootId implements IUuId { private static final long serialVersionUID = 1L; diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IId.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IId.java index 1c3cbb7194f..1ff60e4892d 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IId.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IId.java @@ -25,6 +25,7 @@ * @see IRootId * @see ICompositeId */ +@IdSignature public interface IId extends Serializable { /** diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdCodec.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdCodec.java index b71e2e5c582..b8001012f94 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdCodec.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdCodec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -9,21 +9,32 @@ */ package org.eclipse.scout.rt.dataobject.id; -import static org.eclipse.scout.rt.platform.util.Assertions.assertNotNull; +import static org.eclipse.scout.rt.platform.security.SecurityUtility.createMac; +import static org.eclipse.scout.rt.platform.util.Assertions.*; +import static org.eclipse.scout.rt.platform.util.Base64Utility.encodeUrlSafe; +import static org.eclipse.scout.rt.platform.util.CollectionUtility.hashSet; +import static org.eclipse.scout.rt.platform.util.ObjectUtility.isOneOf; +import static org.eclipse.scout.rt.platform.util.StringUtility.isNullOrEmpty; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; import jakarta.annotation.PostConstruct; import org.eclipse.scout.rt.platform.ApplicationScoped; +import org.eclipse.scout.rt.platform.BEANS; +import org.eclipse.scout.rt.platform.config.AbstractStringConfigProperty; +import org.eclipse.scout.rt.platform.config.CONFIG; import org.eclipse.scout.rt.platform.exception.PlatformException; import org.eclipse.scout.rt.platform.util.LazyValue; import org.eclipse.scout.rt.platform.util.StringUtility; @@ -35,6 +46,7 @@ public class IdCodec { protected static final String ID_TYPENAME_DELIMITER = ":"; + protected static final String SIGNATURE_DELIMITER = "###"; protected final LazyValue m_idFactory = new LazyValue<>(IdFactory.class); protected final LazyValue m_idInventory = new LazyValue<>(IdInventory.class); @@ -42,6 +54,28 @@ public class IdCodec { protected final Map, Function> m_rawTypeFromStringMapper = new HashMap<>(); protected final Map, Function> m_rawTypeToStringMapper = new HashMap<>(); + /** + * Interface for flags used to parametrize conversion between {@link IId} instances and their qualified/unqualified + * representation as {@link String}. This interface is used for all method declarations and allows extension of the + * {@link IdCodecFlag} enum with custom flags. + */ + public interface IIdCodecFlag { + } + + public enum IdCodecFlag implements IIdCodecFlag { + /** + * Does not throw an exception but return {@link UnknownId} if the given string does not match the expected format + * or the referenced class is not found. + */ + LENIENT, + /** + * This will create a signature using the unqualified serialized + * {@link IId} and add it as a suffix. If this suffix is incorrect an error is thrown during deserialization. + * {@link IId}s can be excluded from using signature creation using {@link IdSignature}. + */ + SIGNATURE + } + @PostConstruct protected void initialize() { // setup default type mappings between raw type <--> string @@ -53,6 +87,14 @@ protected void initialize() { registerRawTypeMapper(Locale.class, Locale::forLanguageTag, Locale::toLanguageTag); } + protected IdFactory idFactory() { + return m_idFactory.get(); + } + + protected IdInventory idInventory() { + return m_idInventory.get(); + } + // ---------------- IId to String ---------------- /** @@ -64,21 +106,28 @@ protected void initialize() { * converted to their string representation, separated by ';'. * */ - public String toQualified(IId id) { + public String toQualified(IId id, IIdCodecFlag... flags) { + return toQualified(id, hashSet(flags)); + } + + /** + * @see #toQualified(IId, IIdCodecFlag...) + */ + public String toQualified(IId id, Set flags) { if (id == null) { return null; } - String typeName = m_idInventory.get().getTypeName(id); - if (StringUtility.isNullOrEmpty(typeName)) { + String typeName = idInventory().getTypeName(id); + if (isNullOrEmpty(typeName)) { if (id instanceof UnknownId) { // typeName of unknown id could be null, retain unknown id as-is for later migration - return StringUtility.join(ID_TYPENAME_DELIMITER, ((UnknownId) id).getIdTypeName(), toUnqualified(id)); + return StringUtility.join(ID_TYPENAME_DELIMITER, ((UnknownId) id).getIdTypeName(), toUnqualified(id, flags)); } else { throw new PlatformException("Missing @{} in class {}", IdTypeName.class.getSimpleName(), id.getClass()); } } - return typeName + ID_TYPENAME_DELIMITER + toUnqualified(id); + return typeName + ID_TYPENAME_DELIMITER + toUnqualified(id, flags); } /** @@ -89,7 +138,14 @@ public String toQualified(IId id) { * converted to their string representation, separated by ';'. * */ - public String toUnqualified(IId id) { + public String toUnqualified(IId id, IIdCodecFlag... flags) { + return toUnqualified(id, hashSet(flags)); + } + + /** + * @see #toUnqualified(IId, IIdCodecFlag...) + */ + public String toUnqualified(IId id, Set flags) { if (id == null) { return null; } @@ -99,19 +155,60 @@ public String toUnqualified(IId id) { if (mapper == null) { throw new PlatformException("Missing raw type mapper for wrapped type {}, id type {}", value.getClass(), id.getClass()); } - return mapper.apply(value); + return addSignature(id.getClass(), mapper.apply(value), flags); } else if (id instanceof ICompositeId) { List components = ((ICompositeId) id).unwrap(); - return components.stream() - .map(this::toUnqualified) + // remove signature flag as composites are signed as one and not part by part + Set flagsWithoutSignature = flags.stream() + .filter(Predicate.not(IdCodecFlag.SIGNATURE::equals)) + .collect(Collectors.toSet()); + return addSignature(id.getClass(), components.stream() + .map(comp -> toUnqualified(comp, flagsWithoutSignature)) .map(s -> s == null ? "" : s) // empty string if component is null just in case of composite id - .collect(Collectors.joining(";")); + .collect(Collectors.joining(";")), flags); } else if (id instanceof UnknownId) { - return ((UnknownId) id).getId(); + return addSignature(UnknownId.class, ((UnknownId) id).getId(), flags); + } + return addSignature(id.getClass(), handleToUnqualifiedUnknownIdType(id, flags), flags); + } + + /** + * Adds a signature to the given unqualifiedId iff + *

    + *
  • signatures need to be added to the given idClass (see {@link IdSignature}) + *
  • the given flags contain {@link IdCodecFlag#SIGNATURE} + *
+ * This will create a signature (see {@link #createSignature(String)}) and add it and a delimiter as a suffix to the + * given unqualifiedId. + */ + protected String addSignature(Class idClass, String unqualifiedId, Set flags) { + if (isNullOrEmpty(unqualifiedId) || !isOneOf(IdCodecFlag.SIGNATURE, flags) || !idInventory().isIdSignature(idClass)) { + return unqualifiedId; + } + return unqualifiedId + SIGNATURE_DELIMITER + createSignature(unqualifiedId); + } + + /** + * Create a signature of the given unqualifiedId. Subclasses can override this method and use e.g. the current user id + * as well. + * + * @return an url safe signature + */ + public String createSignature(String unqualifiedId) { + if (isNullOrEmpty(unqualifiedId)) { + return ""; } - return handleToUnqualifiedUnknownIdType(id); + return encodeUrlSafe(createMac(getIdSignaturePassword(), unqualifiedId.getBytes(StandardCharsets.UTF_8))); + } + + /** + * @return private key used to create a signature (see {@link #createSignature(String)}). + */ + protected byte[] getIdSignaturePassword() { + return assertNotNull(CONFIG.getPropertyValue(IdSignaturePasswordProperty.class), "Password property {} not set.", BEANS.get(IdSignaturePasswordProperty.class).getKey()) + .getBytes(StandardCharsets.UTF_8); } // ---------------- String to IId ---------------- @@ -123,18 +220,15 @@ else if (id instanceof UnknownId) { * @throws PlatformException * if the given string does not match the expected format or the referenced class is not found. */ - public IId fromQualified(String qualifiedId) { - return fromQualifiedInternal(qualifiedId, false); + public IId fromQualified(String qualifiedId, IIdCodecFlag... flags) { + return fromQualified(qualifiedId, hashSet(flags)); } /** - * Parses a string in the format {@code [type-name]:[raw-id;raw-id;...]}. - * - * @return {@code IId} parsed from {@code qualifiedId} or {@code null} if the given string does not match the expected - * format or the referenced class is not found. + * @see #fromQualified(String, IIdCodecFlag...) */ - public IId fromQualifiedLenient(String qualifiedId) { - return fromQualifiedInternal(qualifiedId, true); + public IId fromQualified(String qualifiedId, Set flags) { + return fromQualifiedInternal(qualifiedId, flags); } /** @@ -144,14 +238,21 @@ public IId fromQualifiedLenient(String qualifiedId) { * @throws PlatformException * if the given string does not match the expected format */ - public ID fromUnqualified(Class idClass, String unqualifiedId) { + public ID fromUnqualified(Class idClass, String unqualifiedId, IIdCodecFlag... flags) { + return fromUnqualified(idClass, unqualifiedId, hashSet(flags)); + } + + /** + * @see #fromUnqualified(Class, String, IIdCodecFlag...) + */ + public ID fromUnqualified(Class idClass, String unqualifiedId, Set flags) { if (idClass == null) { throw new PlatformException("Missing id class to parse unqualified id {}", unqualifiedId); } - if (StringUtility.isNullOrEmpty(unqualifiedId)) { + if (isNullOrEmpty(unqualifiedId)) { return null; } - return fromUnqualifiedUnchecked(idClass, unqualifiedId); + return fromUnqualifiedUnchecked(idClass, unqualifiedId, flags); } /** @@ -188,23 +289,23 @@ public void unregisterRawTypeMapper(Class rawType) { /** * Callback method to implement if the codec should be extended to handle qualification of unknown {@link IId} types. */ - protected String handleToUnqualifiedUnknownIdType(IId id) { + protected String handleToUnqualifiedUnknownIdType(IId id, Set flags) { throw new PlatformException("Unsupported id type {}, cannot convert id {}", id.getClass(), id); } /** * Parses a string in the format {@code [type-name]:[raw-id;raw-id;...]}. * - * @param lenient - * If the structure of the given {@code qualifiedId} is invalid and {@code lenient} flag is set to - * {@code true}, value {@code null} is returned. If {@code lenient} flag is set to {@code false}, an - * exception is thrown. + * @param flags + * If the structure of the given {@code qualifiedId} is invalid and {@code IdCodecFlag.LENIENT} flag is set, + * value {@code null} is returned. If {@code IdCodecFlag.LENIENT} flag is not set, an exception is thrown. * @return {@code IId} parsed from {@code qualifiedId} */ - protected IId fromQualifiedInternal(String qualifiedId, boolean lenient) { - if (StringUtility.isNullOrEmpty(qualifiedId)) { + protected IId fromQualifiedInternal(String qualifiedId, Set flags) { + if (isNullOrEmpty(qualifiedId)) { return null; } + boolean lenient = isOneOf(IdCodecFlag.LENIENT, flags); String[] tmp = qualifiedId.split(ID_TYPENAME_DELIMITER, 2); // split into at most two parts if (tmp.length < 2) { // no ":" found if (lenient) { @@ -216,7 +317,7 @@ protected IId fromQualifiedInternal(String qualifiedId, boolean lenient) { } } String typeName = tmp[0]; - Class idClass = m_idInventory.get().getIdClass(typeName); + Class idClass = idInventory().getIdClass(typeName); if (idClass == null) { if (lenient) { //noinspection deprecation @@ -228,7 +329,7 @@ protected IId fromQualifiedInternal(String qualifiedId, boolean lenient) { } try { - return fromUnqualified(idClass, tmp[1]); + return fromUnqualified(idClass, tmp[1], flags); } catch (Exception e) { // handle any deserialization issues in lenient mode by retaining the raw id as UnknownId instance @@ -248,17 +349,58 @@ protected IId fromQualifiedInternal(String qualifiedId, boolean lenient) { * @throws PlatformException * if the given string does not match the expected format */ - protected ID fromUnqualifiedUnchecked(Class idClass, String unqualifiedId) { + protected ID fromUnqualifiedUnchecked(Class idClass, String unqualifiedId, Set flags) { + unqualifiedId = removeSignature(idClass, unqualifiedId, flags); String[] rawComponents = unqualifiedId.split(";", -1 /* force empty strings for empty components */); - Object[] components = parseComponents(idClass, rawComponents); - return m_idFactory.get().createInternal(idClass, components); + Object[] components = parseComponents(idClass, rawComponents, flags); + return idFactory().createInternal(idClass, components); + } + + /** + * Removes the signature of the given unqualifiedId iff + *
    + *
  • signatures need to be added to the given idClass (see {@link IdSignature}) + *
  • the given flags contain {@link IdCodecFlag#SIGNATURE} + *
+ * This will split the signed unqualifiedId into the id and its signature and assert the signature's validity. + */ + public String removeSignature(Class idClass, String unqualifiedId, Set flags) { + String[] unqualifiedIdSignatureParts = splitToSignatureParts(unqualifiedId); + assertSignature(idClass, unqualifiedIdSignatureParts, flags); + return unqualifiedIdSignatureParts[0]; + } + + /** + * Assert the validity of the given unqualifiedIdSignatureParts (see {@link #splitToSignatureParts(String)}). The id + * needs to be signed iff + *
    + *
  • signatures need to be added to the given idClass (see {@link IdSignature}) + *
  • the given flags contain {@link IdCodecFlag#SIGNATURE} + *
+ * This will check the presence and a signature if the id needs to be signed and the absence of such a signature if + * the id needs to be unsigned. In addition, the signature is verified for a signed id. + */ + protected void assertSignature(Class idClass, String[] unqualifiedIdSignatureParts, Set flags) { + if (!isOneOf(IdCodecFlag.SIGNATURE, flags) || !idInventory().isIdSignature(idClass)) { + assertEqual(unqualifiedIdSignatureParts.length, 1, "Unqualified id must not be signed."); + return; + } + assertEqual(unqualifiedIdSignatureParts.length, 2, "Unqualified id must be signed."); + assertEqual(unqualifiedIdSignatureParts[1], createSignature(unqualifiedIdSignatureParts[0]), "Signature of unqualified id does not match."); + } + + /** + * Split the given unqualifiedId into id and signature using the {@link #SIGNATURE_DELIMITER}. + */ + protected String[] splitToSignatureParts(String unqualifiedId) { + return unqualifiedId.split(SIGNATURE_DELIMITER); } /** * Parses given {@code rawComponents} based on the declared component types of given {@code idClass}. */ - protected Object[] parseComponents(Class idClass, String[] rawComponents) { - List> componentTypes = m_idFactory.get().getRawTypes(idClass); + protected Object[] parseComponents(Class idClass, String[] rawComponents, Set flags) { + List> componentTypes = idFactory().getRawTypes(idClass); if (!(componentTypes.size() == rawComponents.length)) { throw new PlatformException("Wrong argument size, expected {} parameter, got {} raw components {}, idType={}", componentTypes.size(), rawComponents.length, Arrays.toString(rawComponents), idClass.getName()); } @@ -272,7 +414,7 @@ protected Object[] parseComponents(Class idClass, String[] rawCom } try { String raw = rawComponents[i]; - if (StringUtility.isNullOrEmpty(raw)) { + if (isNullOrEmpty(raw)) { components[i] = null; } else { @@ -285,4 +427,17 @@ protected Object[] parseComponents(Class idClass, String[] rawCom } return components; } + + public static class IdSignaturePasswordProperty extends AbstractStringConfigProperty { + + @Override + public String getKey() { + return "scout.idSignaturePassword"; + } + + @Override + public String description() { + return "Password to create signatures for ids that are serialized or deserialized. The value of this password must be equal for all parts of an application."; + } + } } diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdInventory.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdInventory.java index 19fa060d302..0f2ef107480 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdInventory.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdInventory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -29,8 +29,10 @@ public class IdInventory { private static final Logger LOG = LoggerFactory.getLogger(IdInventory.class); + protected final Map> m_nameToClassMap = new HashMap<>(); protected final Map, String> m_classToNameMap = new HashMap<>(); + protected final Map, Boolean> m_classToIdSignatureMap = new HashMap<>(); @PostConstruct protected void createClassCache() { @@ -46,6 +48,18 @@ protected void createClassCache() { } } LOG.debug("Registered {} id types", m_nameToClassMap.size()); + + for (IClassInfo classInfo : ClassInventory.get().getKnownAnnotatedTypes(IdSignature.class)) { + Class idClass = classInfo.resolveClass(); + if (IId.class.isAssignableFrom(idClass)) { + //noinspection unchecked + registerIdSignature((Class) idClass, idClass.getAnnotation(IdSignature.class).value()); + } + else { + LOG.warn("Class {} is annotated with @{} but does not implement {}. Skipping class.", idClass.getName(), IdSignature.class.getSimpleName(), IId.class.getName()); + } + } + LOG.debug("Registered {} id signature mappings", m_classToIdSignatureMap.size()); } /** @@ -69,6 +83,17 @@ protected void checkDuplicateIdTypeNames(Class clazz, String typeName, Class< assertNull(existingName, "{} is annotated with @{} value '{}', but was already registered with type name '{}'. Register each class only once.", clazz, IdTypeName.class.getSimpleName(), typeName, existingName); } + /** + * Register id class with {@link IdSignature} annotation present. + *

+ * Note: The access to the data structure is not synchronized and therefore not thread safe. Use this method to set up + * the {@link IdInventory} instance directly after platform start and not to change the {@link IdInventory} behavior + * dynamically at runtime. + */ + public void registerIdSignature(Class idClass, boolean signature) { + m_classToIdSignatureMap.put(idClass, signature); + } + /** * @return the type name of the id class as defined by the {@link IdTypeName} annotation or null if the * annotation is not present. @@ -96,4 +121,32 @@ public String getTypeName(IId id) { public Class getIdClass(String typeName) { return m_nameToClassMap.get(typeName); } + + /** + * @return Whether the {@link IId} needs to be serialized and deserialized using a signature or not. For more details + * see {@link IdSignature}. + */ + public boolean isIdSignature(Class idClass) { + synchronized (m_classToIdSignatureMap) { + if (m_classToIdSignatureMap.containsKey(idClass)) { + return m_classToIdSignatureMap.get(idClass); + } + + boolean signature; + IdSignature idSignature = idClass.getAnnotation(IdSignature.class); + if (idSignature != null) { + signature = idSignature.value(); + } + else if (idClass.getSuperclass() != null && IId.class.isAssignableFrom(idClass.getSuperclass())) { + //noinspection unchecked + signature = isIdSignature((Class) idClass.getSuperclass()); + } + else { + signature = IId.class.getAnnotation(IdSignature.class).value(); + } + + m_classToIdSignatureMap.put(idClass, signature); + return m_classToIdSignatureMap.get(idClass); + } + } } diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdSignature.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdSignature.java new file mode 100644 index 00000000000..008d1827d0d --- /dev/null +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdSignature.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.dataobject.id; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates whether an {@link IId} is serialized and deserialized using a signature or not. This annotation is inherited + * and can be overridden by subclasses. Only annotations from superclasses are inherited, interfaces are not taken into + * account. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface IdSignature { + /** + * Whether signature creation is enabled or not. Default is {@code true}. + */ + boolean value() default true; +} diff --git a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdTypeName.java b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdTypeName.java index acbc31047dd..71e9524686a 100644 --- a/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdTypeName.java +++ b/org.eclipse.scout.rt.dataobject/src/main/java/org/eclipse/scout/rt/dataobject/id/IdTypeName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,12 +17,14 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IIdCodecFlag; + /** * Annotation used to define the unique type name for an {@link IId} class, used when serializing or deserializing * instances. * - * @see IdCodec#toQualified(IId) - * @see IdCodec#fromQualified(String) + * @see IdCodec#toQualified(IId, IIdCodecFlag...) + * @see IdCodec#fromQualified(String, IIdCodecFlag...) * @see TypedId */ @Documented diff --git a/org.eclipse.scout.rt.jackson.test/src/test/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializationTest.java b/org.eclipse.scout.rt.jackson.test/src/test/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializationTest.java index 4dfecbe40d1..77305c6bcd6 100644 --- a/org.eclipse.scout.rt.jackson.test/src/test/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializationTest.java +++ b/org.eclipse.scout.rt.jackson.test/src/test/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -117,7 +117,7 @@ protected static class QualifiedIIdSerializationTest_DataObjectSerializerProvide @Override public JsonSerializer findSerializer(ScoutDataObjectModuleContext moduleContext, JavaType type, SerializationConfig config, BeanDescription beanDesc) { if (type.hasRawClass(FixtureStringId.class) || type.hasRawClass(FixtureUuId.class) || type.hasRawClass(FixtureCompositeId.class)) { - return new QualifiedIIdSerializer(); + return new QualifiedIIdSerializer(moduleContext); } return null; @@ -134,7 +134,7 @@ public JsonDeserializer findDeserializer(ScoutDataObjectModuleContext moduleC @Override public JsonSerializer findKeySerializer(ScoutDataObjectModuleContext moduleContext, JavaType type, SerializationConfig config, BeanDescription beanDesc) { if (type.hasRawClass(FixtureStringId.class) || type.hasRawClass(FixtureUuId.class) || type.hasRawClass(FixtureCompositeId.class)) { - return new QualifiedIIdMapKeySerializer(); + return new QualifiedIIdMapKeySerializer(moduleContext); } return null; } diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/JacksonIdSignatureDataObjectMapper.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/JacksonIdSignatureDataObjectMapper.java new file mode 100644 index 00000000000..40ef09d9a9f --- /dev/null +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/JacksonIdSignatureDataObjectMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.jackson.dataobject; + +import org.eclipse.scout.rt.dataobject.IDataObjectMapper; +import org.eclipse.scout.rt.dataobject.IIdSignatureDataObjectMapper; +import org.eclipse.scout.rt.platform.IBean; +import org.eclipse.scout.rt.platform.Order; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * {@link IDataObjectMapper} implementation based on jackson {@link ObjectMapper} with id signed + * serialization/deserialization. + */ +@Order(IBean.DEFAULT_BEAN_ORDER + 100) +public class JacksonIdSignatureDataObjectMapper extends JacksonDataObjectMapper implements IIdSignatureDataObjectMapper { + + @Override + protected void prepareScoutDataModuleContext(ScoutDataObjectModuleContext moduleContext) { + super.prepareScoutDataModuleContext(moduleContext); + moduleContext.withIdSignature(true); + } +} diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectModuleContext.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectModuleContext.java index a1198a09330..f4972c966c9 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectModuleContext.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectModuleContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -41,6 +41,8 @@ public class ScoutDataObjectModuleContext { protected static final String LENIENT_MODE_KEY = "lenientModeKey"; + protected static final String ID_SIGNATURE_KEY = "idSignatureKey"; + protected LazyValue m_comparator = new LazyValue<>(() -> BEANS.get(DoEntitySerializerAttributeNameComparator.class).init(this)); protected final Map m_contextMap = new HashMap<>(); @@ -138,7 +140,16 @@ public boolean isLenientMode() { } public ScoutDataObjectModuleContext withLenientMode(boolean lenientMode) { - put(LENIENT_MODE_KEY, true); + put(LENIENT_MODE_KEY, lenientMode); + return this; + } + + public boolean isIdSignature() { + return BooleanUtility.nvl(get(ID_SIGNATURE_KEY, Boolean.class)); + } + + public ScoutDataObjectModuleContext withIdSignature(boolean idSignature) { + put(ID_SIGNATURE_KEY, idSignature); return this; } } diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectSerializerProvider.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectSerializerProvider.java index 64e78e0c6af..bf1ad929439 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectSerializerProvider.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/ScoutDataObjectSerializerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -75,14 +75,14 @@ else if (BinaryResource.class.isAssignableFrom(rawClass)) { } else if (IId.class.isAssignableFrom(rawClass)) { if (type.isConcrete()) { - return new UnqualifiedIIdSerializer(type); + return new UnqualifiedIIdSerializer(moduleContext, type); } else { - return new QualifiedIIdSerializer(); + return new QualifiedIIdSerializer(moduleContext); } } else if (TypedId.class.isAssignableFrom(rawClass)) { - return new TypedIdSerializer(); + return new TypedIdSerializer(moduleContext); } else if (IEnum.class.isAssignableFrom(rawClass)) { return new EnumSerializer(type); @@ -125,7 +125,7 @@ else if (BinaryResource.class.isAssignableFrom(rawClass)) { else if (IId.class.isAssignableFrom(rawClass)) { Class idClass = rawClass.asSubclass(IId.class); if (type.isConcrete()) { - return new UnqualifiedIIdDeserializer(idClass); + return new UnqualifiedIIdDeserializer(moduleContext, idClass); } else { return new QualifiedIIdDeserializer(moduleContext, idClass); @@ -146,10 +146,10 @@ public JsonSerializer findKeySerializer(ScoutDataObjectModuleContext moduleCo } if (IId.class.isAssignableFrom(rawClass)) { if (type.isConcrete()) { - return new UnqualifiedIIdMapKeySerializer(); + return new UnqualifiedIIdMapKeySerializer(moduleContext); } else { - return new QualifiedIIdMapKeySerializer(); + return new QualifiedIIdMapKeySerializer(moduleContext); } } if (IEnum.class.isAssignableFrom(rawClass)) { diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecDeserializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecDeserializer.java new file mode 100644 index 00000000000..beff5a47541 --- /dev/null +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecDeserializer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.jackson.dataobject.id; + +import static java.util.Collections.unmodifiableSet; + +import java.util.Set; + +import org.eclipse.scout.rt.dataobject.id.IdCodec; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IIdCodecFlag; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; +import org.eclipse.scout.rt.platform.util.LazyValue; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +/** + * Abstract {@link StdDeserializer} with {@link ScoutDataObjectModuleContext} that provides an {@link IdCodec} and + * information about the {@link IIdCodecFlag}s of the context. + */ +public abstract class AbstractIdCodecDeserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + protected final ScoutDataObjectModuleContext m_moduleContext; + + protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); + protected final LazyValue> m_idCodecFlags = new LazyValue<>(() -> unmodifiableSet(computeIdCodecFlags())); + + public AbstractIdCodecDeserializer(ScoutDataObjectModuleContext moduleContext, Class valueClass) { + super(valueClass); + m_moduleContext = moduleContext; + } + + public AbstractIdCodecDeserializer(ScoutDataObjectModuleContext moduleContext, JavaType valueType) { + super(valueType); + m_moduleContext = moduleContext; + } + + protected ScoutDataObjectModuleContext moduleContext() { + return m_moduleContext; + } + + protected IdCodec idCodec() { + return m_idCodec.get(); + } + + protected Set computeIdCodecFlags() { + return IdCodecUtility.getIdCodecFlags(moduleContext()); + } + + protected Set idCodecFlags() { + return m_idCodecFlags.get(); + } +} diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeyDeserializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeyDeserializer.java new file mode 100644 index 00000000000..6469db2db69 --- /dev/null +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeyDeserializer.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.jackson.dataobject.id; + +import static java.util.Collections.unmodifiableSet; + +import java.util.Set; + +import org.eclipse.scout.rt.dataobject.id.IdCodec; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IIdCodecFlag; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; +import org.eclipse.scout.rt.platform.util.LazyValue; + +import com.fasterxml.jackson.databind.KeyDeserializer; + +/** + * Abstract {@link KeyDeserializer} with {@link ScoutDataObjectModuleContext} that provides an {@link IdCodec} and + * information about the {@link IIdCodecFlag}s of the context. + */ +public abstract class AbstractIdCodecMapKeyDeserializer extends KeyDeserializer { + + protected final ScoutDataObjectModuleContext m_moduleContext; + + protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); + protected final LazyValue> m_idCodecFlags = new LazyValue<>(() -> unmodifiableSet(computeIdCodecFlags())); + + public AbstractIdCodecMapKeyDeserializer(ScoutDataObjectModuleContext moduleContext) { + m_moduleContext = moduleContext; + } + + protected ScoutDataObjectModuleContext moduleContext() { + return m_moduleContext; + } + + protected IdCodec idCodec() { + return m_idCodec.get(); + } + + protected Set computeIdCodecFlags() { + return IdCodecUtility.getIdCodecFlags(moduleContext()); + } + + protected Set idCodecFlags() { + return m_idCodecFlags.get(); + } +} diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeySerializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeySerializer.java new file mode 100644 index 00000000000..e1734a1635e --- /dev/null +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecMapKeySerializer.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.jackson.dataobject.id; + +import static java.util.Collections.unmodifiableSet; + +import java.util.Set; + +import org.eclipse.scout.rt.dataobject.id.IdCodec; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IIdCodecFlag; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; +import org.eclipse.scout.rt.platform.util.LazyValue; + +import com.fasterxml.jackson.databind.JsonSerializer; + +/** + * Abstract {@link JsonSerializer} with {@link ScoutDataObjectModuleContext} that provides an {@link IdCodec} and + * information about the {@link IIdCodecFlag}s of the context. + */ +public abstract class AbstractIdCodecMapKeySerializer extends JsonSerializer { + + protected final ScoutDataObjectModuleContext m_moduleContext; + + protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); + protected final LazyValue> m_idCodecFlags = new LazyValue<>(() -> unmodifiableSet(computeIdCodecFlags())); + + public AbstractIdCodecMapKeySerializer(ScoutDataObjectModuleContext moduleContext) { + m_moduleContext = moduleContext; + } + + protected ScoutDataObjectModuleContext moduleContext() { + return m_moduleContext; + } + + protected IdCodec idCodec() { + return m_idCodec.get(); + } + + protected Set computeIdCodecFlags() { + return IdCodecUtility.getIdCodecFlags(moduleContext()); + } + + protected Set idCodecFlags() { + return m_idCodecFlags.get(); + } +} diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecSerializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecSerializer.java new file mode 100644 index 00000000000..95afc08b87d --- /dev/null +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/AbstractIdCodecSerializer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.jackson.dataobject.id; + +import static java.util.Collections.unmodifiableSet; + +import java.util.Set; + +import org.eclipse.scout.rt.dataobject.id.IdCodec; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IIdCodecFlag; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; +import org.eclipse.scout.rt.platform.util.LazyValue; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +/** + * Abstract {@link StdSerializer} with {@link ScoutDataObjectModuleContext} that provides an {@link IdCodec} and + * information about the {@link IIdCodecFlag}s of the context. + */ +public abstract class AbstractIdCodecSerializer extends StdSerializer { + private static final long serialVersionUID = 1L; + + protected final ScoutDataObjectModuleContext m_moduleContext; + + protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); + protected final LazyValue> m_idCodecFlags = new LazyValue<>(() -> unmodifiableSet(computeIdCodecFlags())); + + public AbstractIdCodecSerializer(ScoutDataObjectModuleContext moduleContext, Class valueClass) { + super(valueClass, false); + m_moduleContext = moduleContext; + } + + public AbstractIdCodecSerializer(ScoutDataObjectModuleContext moduleContext, JavaType valueType) { + super(valueType); + m_moduleContext = moduleContext; + } + + protected ScoutDataObjectModuleContext moduleContext() { + return m_moduleContext; + } + + protected IdCodec idCodec() { + return m_idCodec.get(); + } + + protected Set computeIdCodecFlags() { + return IdCodecUtility.getIdCodecFlags(moduleContext()); + } + + protected Set idCodecFlags() { + return m_idCodecFlags.get(); + } +} diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/IdCodecUtility.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/IdCodecUtility.java new file mode 100644 index 00000000000..f37dc1c38de --- /dev/null +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/IdCodecUtility.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.jackson.dataobject.id; + +import java.util.Set; + +import org.eclipse.scout.rt.dataobject.id.IdCodec.IIdCodecFlag; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IdCodecFlag; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; +import org.eclipse.scout.rt.platform.util.CollectionUtility; + +public final class IdCodecUtility { + + private IdCodecUtility() { + } + + /** + * Computes the {@link IIdCodecFlag}s for the given {@link ScoutDataObjectModuleContext}. E.g.: + * {@link IdCodecFlag#SIGNATURE} if {@link ScoutDataObjectModuleContext#isIdSignature()} returns {@code true}. The + * resulting set is mutable. + */ + public static Set getIdCodecFlags(ScoutDataObjectModuleContext moduleContext) { + var flags = CollectionUtility. emptyHashSet(); + if (moduleContext == null) { + return flags; + } + if (moduleContext.isLenientMode()) { + flags.add(IdCodecFlag.LENIENT); + } + if (moduleContext.isIdSignature()) { + flags.add(IdCodecFlag.SIGNATURE); + } + return flags; + } +} diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdDeserializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdDeserializer.java index 90a4f645575..66afc73f339 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdDeserializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -10,46 +10,43 @@ package org.eclipse.scout.rt.jackson.dataobject.id; import static org.eclipse.scout.rt.platform.util.Assertions.assertInstance; +import static org.eclipse.scout.rt.platform.util.ObjectUtility.isOneOf; import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; import org.eclipse.scout.rt.dataobject.id.IdCodec; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IdCodecFlag; import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; -import org.eclipse.scout.rt.platform.util.LazyValue; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; /** * Custom deserializer for {@link IId} instances - like {@link TypedIdDeserializer} it uses {@link IdCodec} for * serialization. It may be used as a replacement for {@link UnqualifiedIIdDeserializer}. */ -public class QualifiedIIdDeserializer extends StdDeserializer { +public class QualifiedIIdDeserializer extends AbstractIdCodecDeserializer { private static final long serialVersionUID = 1L; - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); protected final Class m_idClass; - protected final ScoutDataObjectModuleContext m_moduleContext; - - public QualifiedIIdDeserializer(ScoutDataObjectModuleContext context, Class idClass) { - super(idClass); + public QualifiedIIdDeserializer(ScoutDataObjectModuleContext moduleContext, Class idClass) { + super(moduleContext, idClass); m_idClass = idClass; - m_moduleContext = context; } @Override public IId deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String rawValue = p.getText(); try { - if (m_moduleContext.isLenientMode()) { - return m_idCodec.get().fromQualifiedLenient(rawValue); + IId id = idCodec().fromQualified(rawValue, idCodecFlags()); + if (!isOneOf(IdCodecFlag.LENIENT, idCodecFlags())) { + // check required to prevent returning an instance that isn't compatible with requested ID class + assertInstance(id, m_idClass); } - // check required to prevent returning an instance that isn't compatible with requested ID class - return assertInstance(m_idCodec.get().fromQualified(rawValue), m_idClass); + return id; } catch (RuntimeException e) { throw InvalidFormatException.from(p, "Failed to deserialize qualified IId: " + e.getMessage(), rawValue, m_idClass); diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeyDeserializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeyDeserializer.java index 7931d398271..8aec4f827da 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeyDeserializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeyDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -10,42 +10,40 @@ package org.eclipse.scout.rt.jackson.dataobject.id; import static org.eclipse.scout.rt.platform.util.Assertions.assertInstance; +import static org.eclipse.scout.rt.platform.util.ObjectUtility.isOneOf; import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; import org.eclipse.scout.rt.dataobject.id.IdCodec; +import org.eclipse.scout.rt.dataobject.id.IdCodec.IdCodecFlag; import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; -import org.eclipse.scout.rt.platform.util.LazyValue; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; /** * Custom deserializer for {@link IId} instances - like {@link TypedIdDeserializer} it uses {@link IdCodec} for * serialization. It may be used as a replacement for {@link UnqualifiedIIdDeserializer}. */ -public class QualifiedIIdMapKeyDeserializer extends KeyDeserializer { +public class QualifiedIIdMapKeyDeserializer extends AbstractIdCodecMapKeyDeserializer { - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); - - protected final ScoutDataObjectModuleContext m_moduleContext; protected final Class m_idClass; public QualifiedIIdMapKeyDeserializer(ScoutDataObjectModuleContext moduleContext, Class idClass) { - m_moduleContext = moduleContext; + super(moduleContext); m_idClass = idClass; } @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { try { - if (m_moduleContext.isLenientMode()) { - return m_idCodec.get().fromQualifiedLenient(key); + IId id = idCodec().fromQualified(key, idCodecFlags()); + if (!isOneOf(IdCodecFlag.LENIENT, idCodecFlags())) { + // check required to prevent returning an instance that isn't compatible with requested ID class + assertInstance(id, m_idClass); } - // check required to prevent returning an instance that isn't compatible with requested ID class - return assertInstance(m_idCodec.get().fromQualified(key), m_idClass); + return id; } catch (RuntimeException e) { throw InvalidFormatException.from(null, "Failed to deserialize qualified IId map key: " + e.getMessage(), key, m_idClass); diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeySerializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeySerializer.java index 860a450a9c3..9ef3083f11f 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeySerializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdMapKeySerializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -13,22 +13,23 @@ import org.eclipse.scout.rt.dataobject.id.IId; import org.eclipse.scout.rt.dataobject.id.IdCodec; -import org.eclipse.scout.rt.platform.util.LazyValue; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; /** * Custom serializer for {@link IId} instances - like {@link TypedIdSerializer} it uses {@link IdCodec} for * serialization. It may be used as a replacement for {@link UnqualifiedIIdMapKeySerializer}. */ -public class QualifiedIIdMapKeySerializer extends JsonSerializer { +public class QualifiedIIdMapKeySerializer extends AbstractIdCodecMapKeySerializer { - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); + public QualifiedIIdMapKeySerializer(ScoutDataObjectModuleContext moduleContext) { + super(moduleContext); + } @Override public void serialize(IId value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeFieldName(m_idCodec.get().toQualified(value)); + gen.writeFieldName(idCodec().toQualified(value, idCodecFlags())); } } diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializer.java index 994fdc37815..e0cb68b4221 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/QualifiedIIdSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -13,27 +13,24 @@ import org.eclipse.scout.rt.dataobject.id.IId; import org.eclipse.scout.rt.dataobject.id.IdCodec; -import org.eclipse.scout.rt.platform.util.LazyValue; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** * Custom serializer for {@link IId} instances - like {@link TypedIdSerializer} it uses {@link IdCodec} for * serialization. It may be used as a replacement for {@link UnqualifiedIIdSerializer}. */ -public class QualifiedIIdSerializer extends StdSerializer { +public class QualifiedIIdSerializer extends AbstractIdCodecSerializer { private static final long serialVersionUID = 1L; - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); - - public QualifiedIIdSerializer() { - super(IId.class, false); + public QualifiedIIdSerializer(ScoutDataObjectModuleContext moduleContext) { + super(moduleContext, IId.class); } @Override public void serialize(IId value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeString(m_idCodec.get().toQualified(value)); + gen.writeString(idCodec().toQualified(value, idCodecFlags())); } } diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdDeserializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdDeserializer.java index ee431284cd3..728bb47977b 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdDeserializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,38 +12,28 @@ import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; -import org.eclipse.scout.rt.dataobject.id.IdCodec; import org.eclipse.scout.rt.dataobject.id.TypedId; import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; -import org.eclipse.scout.rt.platform.util.LazyValue; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; /** * Custom deserializer for {@link TypedId} values. */ -public class TypedIdDeserializer extends StdDeserializer> { +public class TypedIdDeserializer extends AbstractIdCodecDeserializer> { private static final long serialVersionUID = 1L; - protected final ScoutDataObjectModuleContext m_moduleContext; - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); - public TypedIdDeserializer(ScoutDataObjectModuleContext moduleContext) { - super(TypedId.class); - m_moduleContext = moduleContext; + super(moduleContext, TypedId.class); } @Override public TypedId deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String rawValue = p.getText(); try { - if (m_moduleContext.isLenientMode()) { - return TypedId.of(m_idCodec.get().fromQualifiedLenient(rawValue)); - } - return TypedId.of(m_idCodec.get().fromQualified(rawValue)); + return TypedId.of(idCodec().fromQualified(rawValue, idCodecFlags())); } catch (RuntimeException e) { throw InvalidFormatException.from(p, "Failed to deserialize TypedId: " + e.getMessage(), rawValue, TypedId.class); diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdSerializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdSerializer.java index 64eb4368962..9feb8448c44 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdSerializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/TypedIdSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,28 +12,24 @@ import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; -import org.eclipse.scout.rt.dataobject.id.IdCodec; import org.eclipse.scout.rt.dataobject.id.TypedId; -import org.eclipse.scout.rt.platform.util.LazyValue; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** * Custom serializer for all {@link TypedId} instances. */ -public class TypedIdSerializer extends StdSerializer> { +public class TypedIdSerializer extends AbstractIdCodecSerializer> { private static final long serialVersionUID = 1L; - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); - - public TypedIdSerializer() { - super(TypedId.class, false); + public TypedIdSerializer(ScoutDataObjectModuleContext moduleContext) { + super(moduleContext, TypedId.class); } @Override public void serialize(TypedId value, JsonGenerator gen, SerializerProvider provider) throws IOException { - gen.writeString(m_idCodec.get().toQualified(value.getId())); + gen.writeString(idCodec().toQualified(value.getId(), idCodecFlags())); } } diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdDeserializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdDeserializer.java index cc0d809e609..722b8bdebc3 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdDeserializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,25 +12,22 @@ import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; -import org.eclipse.scout.rt.dataobject.id.IdCodec; -import org.eclipse.scout.rt.platform.util.LazyValue; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; /** * Custom deserializer for {@link IId} values. */ -public class UnqualifiedIIdDeserializer extends StdDeserializer { +public class UnqualifiedIIdDeserializer extends AbstractIdCodecDeserializer { private static final long serialVersionUID = 1L; - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); protected final Class m_idClass; - public UnqualifiedIIdDeserializer(Class idClass) { - super(idClass); + public UnqualifiedIIdDeserializer(ScoutDataObjectModuleContext moduleContext, Class idClass) { + super(moduleContext, idClass); m_idClass = idClass; } @@ -38,7 +35,7 @@ public UnqualifiedIIdDeserializer(Class idClass) { public IId deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String rawValue = p.getText(); try { - return m_idCodec.get().fromUnqualified(m_idClass, rawValue); + return idCodec().fromUnqualified(m_idClass, rawValue, idCodecFlags()); } catch (RuntimeException e) { throw InvalidFormatException.from(p, "Failed to deserialize unqualified IId: " + e.getMessage(), rawValue, m_idClass); diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeyDeserializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeyDeserializer.java index 90e41fae015..8b75b3445a8 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeyDeserializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeyDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,33 +12,27 @@ import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; -import org.eclipse.scout.rt.dataobject.id.IdCodec; import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; -import org.eclipse.scout.rt.platform.util.LazyValue; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.exc.InvalidFormatException; /** * Custom deserializer used for map keys of type {@link IId}. */ -public class UnqualifiedIIdMapKeyDeserializer extends KeyDeserializer { +public class UnqualifiedIIdMapKeyDeserializer extends AbstractIdCodecMapKeyDeserializer { - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); - - protected final ScoutDataObjectModuleContext m_moduleContext; protected final Class m_idClass; public UnqualifiedIIdMapKeyDeserializer(ScoutDataObjectModuleContext moduleContext, Class idClass) { - m_moduleContext = moduleContext; + super(moduleContext); m_idClass = idClass; } @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { try { - return m_idCodec.get().fromUnqualified(m_idClass, key); + return idCodec().fromUnqualified(m_idClass, key, idCodecFlags()); } catch (RuntimeException e) { if (m_moduleContext.isLenientMode()) { diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeySerializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeySerializer.java index 5b8995d3897..56265409efc 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeySerializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdMapKeySerializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,22 +12,22 @@ import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; -import org.eclipse.scout.rt.dataobject.id.IdCodec; -import org.eclipse.scout.rt.platform.util.LazyValue; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; /** * Custom serializer used for map keys of type {@link IId}. */ -public class UnqualifiedIIdMapKeySerializer extends JsonSerializer { +public class UnqualifiedIIdMapKeySerializer extends AbstractIdCodecMapKeySerializer { - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); + public UnqualifiedIIdMapKeySerializer(ScoutDataObjectModuleContext moduleContext) { + super(moduleContext); + } @Override public void serialize(IId value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeFieldName(m_idCodec.get().toUnqualified(value)); + gen.writeFieldName(idCodec().toUnqualified(value, idCodecFlags())); } } diff --git a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdSerializer.java b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdSerializer.java index 267a031bb82..f9ca22d0094 100644 --- a/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdSerializer.java +++ b/org.eclipse.scout.rt.jackson/src/main/java/org/eclipse/scout/rt/jackson/dataobject/id/UnqualifiedIIdSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,28 +12,24 @@ import java.io.IOException; import org.eclipse.scout.rt.dataobject.id.IId; -import org.eclipse.scout.rt.dataobject.id.IdCodec; -import org.eclipse.scout.rt.platform.util.LazyValue; +import org.eclipse.scout.rt.jackson.dataobject.ScoutDataObjectModuleContext; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** * Custom serializer for all {@link IId} instances. */ -public class UnqualifiedIIdSerializer extends StdSerializer { +public class UnqualifiedIIdSerializer extends AbstractIdCodecSerializer { private static final long serialVersionUID = 1L; - protected final LazyValue m_idCodec = new LazyValue<>(IdCodec.class); - - public UnqualifiedIIdSerializer(JavaType type) { - super(type); + public UnqualifiedIIdSerializer(ScoutDataObjectModuleContext moduleContext, JavaType type) { + super(moduleContext, type); } @Override public void serialize(IId value, JsonGenerator gen, SerializerProvider provider) throws IOException { - gen.writeObject(m_idCodec.get().toUnqualified(value)); + gen.writeObject(idCodec().toUnqualified(value, idCodecFlags())); } } diff --git a/org.eclipse.scout.rt.rest.jersey.client/pom.xml b/org.eclipse.scout.rt.rest.jersey.client/pom.xml index 04168794705..fb51434e2c6 100644 --- a/org.eclipse.scout.rt.rest.jersey.client/pom.xml +++ b/org.eclipse.scout.rt.rest.jersey.client/pom.xml @@ -1,6 +1,6 @@ @@ -38,5 +42,9 @@ org.glassfish.jersey.core jersey-client + + org.glassfish.jersey.media + jersey-media-json-jackson + diff --git a/org.eclipse.scout.rt.rest.jersey.client/src/main/java/org/eclipse/scout/rt/rest/jersey/client/IdSignatureRestClientFilter.java b/org.eclipse.scout.rt.rest.jersey.client/src/main/java/org/eclipse/scout/rt/rest/jersey/client/IdSignatureRestClientFilter.java new file mode 100644 index 00000000000..89d61b37df5 --- /dev/null +++ b/org.eclipse.scout.rt.rest.jersey.client/src/main/java/org/eclipse/scout/rt/rest/jersey/client/IdSignatureRestClientFilter.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2010, 2024 BSI Business Systems Integration AG + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.scout.rt.rest.jersey.client; + +import java.io.IOException; + +import jakarta.annotation.Priority; +import jakarta.ws.rs.Priorities; +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.client.ClientResponseContext; +import jakarta.ws.rs.core.MultivaluedMap; + +import org.eclipse.scout.rt.jackson.dataobject.JacksonIdSignatureDataObjectMapper; +import org.eclipse.scout.rt.platform.BEANS; +import org.eclipse.scout.rt.platform.Bean; +import org.eclipse.scout.rt.rest.client.IGlobalRestRequestFilter; +import org.eclipse.scout.rt.rest.client.IGlobalRestResponseFilter; +import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.EndpointConfigBase; +import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.ObjectReaderInjector; +import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.ObjectReaderModifier; +import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.ObjectWriterInjector; +import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.ObjectWriterModifier; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; + +/** + * Filter that adds an object mapper supporting signature creation for serialization/deserialization of request and + * response. This feature can be enabled depending on the context e.g. headers of the request. By default, it checks the + * {@link IdSignatureRestClientFilter#ID_SIGNATURE_HTTP_HEADER}. + */ +@Priority(Priorities.ENTITY_CODER) +public class IdSignatureRestClientFilter implements IGlobalRestRequestFilter, IGlobalRestResponseFilter { + public static final String ID_SIGNATURE_HTTP_HEADER = "X-ScoutIdSignature"; + + @Override + public void filter(ClientRequestContext requestContext) throws IOException { + ObjectWriterInjector.set(null); + if (!enableSignature(requestContext)) { + return; + } + ObjectWriterInjector.set(BEANS.get(IdSignatureObjectWriterModifier.class)); + } + + @Override + public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { + ObjectReaderInjector.set(null); + if (!enableSignature(requestContext, responseContext)) { + return; + } + ObjectReaderInjector.set(BEANS.get(IdSignatureObjectReaderModifier.class)); + } + + /** + * Check the {@link ClientRequestContext} and {@link ClientResponseContext} if signature creation needs to be enabled. + * Default implementation returns {@code false}. + */ + protected boolean enableSignature(ClientRequestContext requestContext, ClientResponseContext responseContext) { + return enableSignature(requestContext) || enableSignature(responseContext); + } + + /** + * Check the {@link ClientRequestContext} if signature creation needs to be enabled. Default implementation checks the + * {@link IdSignatureRestClientFilter#ID_SIGNATURE_HTTP_HEADER}. + */ + protected boolean enableSignature(ClientRequestContext requestContext) { + return Boolean.TRUE.toString().equalsIgnoreCase(requestContext.getHeaderString(ID_SIGNATURE_HTTP_HEADER)); + } + + /** + * Check the {@link ClientResponseContext} if signature creation needs to be enabled. Default implementation returns + * {@code false}. + */ + protected boolean enableSignature(ClientResponseContext responseContext) { + return false; + } + + @Bean + public static class IdSignatureObjectReaderModifier extends ObjectReaderModifier { + + @Override + public ObjectReader modify(EndpointConfigBase endpoint, MultivaluedMap httpHeaders, JavaType resultType, ObjectReader r, JsonParser p) { + //noinspection deprecation + var objectMapper = BEANS.get(JacksonIdSignatureDataObjectMapper.class).getObjectMapper(); + p.setCodec(objectMapper); + return objectMapper.readerFor(r.getValueType()); + } + } + + @Bean + public static class IdSignatureObjectWriterModifier extends ObjectWriterModifier { + + @Override + public ObjectWriter modify(EndpointConfigBase endpoint, MultivaluedMap responseHeaders, Object valueToWrite, ObjectWriter w, JsonGenerator g) { + //noinspection deprecation + var objectMapper = BEANS.get(JacksonIdSignatureDataObjectMapper.class).getObjectMapper(); + g.setCodec(objectMapper); + return objectMapper.writer(); + } + } +} diff --git a/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.resources.prefs b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..13d34f372ba --- /dev/null +++ b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,18 @@ +eclipse.preferences.version=1 +encoding//src/main/client=UTF-8 +encoding//src/main/fixture=UTF-8 +encoding//src/main/java=UTF-8 +encoding//src/main/java-jcl=UTF-8 +encoding//src/main/java-log4j=UTF-8 +encoding//src/main/java-original=UTF-8 +encoding//src/main/js=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/main/shared=UTF-8 +encoding//src/main/webapp=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/js=UTF-8 +encoding//src/test/resources=UTF-8 +encoding//target/generated-sources/annotations=UTF-8 +encoding//target/generated-sources/wsimport=UTF-8 +encoding/=UTF-8 +encoding/files=UTF-8 diff --git a/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 00000000000..5a0ad22d2a7 --- /dev/null +++ b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +line.separator=\n diff --git a/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.apt.core.prefs b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 00000000000..d4313d4b25e --- /dev/null +++ b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=false diff --git a/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..91af6f20512 --- /dev/null +++ b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,399 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes=m_ +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=16 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=2 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=true +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=true +org.eclipse.jdt.core.formatter.lineSplit=240 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=2 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.launching.prefs b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.launching.prefs new file mode 100644 index 00000000000..d211d326335 --- /dev/null +++ b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.launching.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning diff --git a/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000000..a52f8c4ad0a --- /dev/null +++ b/org.eclipse.scout.rt.rest.jersey.server/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,127 @@ +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=false +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_functional_interfaces=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=true +cleanup.format_source_code=true +cleanup.format_source_code_changes_only=false +cleanup.insert_inferred_type_arguments=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=true +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=false +cleanup.qualify_static_member_accesses_with_declaring_class=false +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_redundant_type_arguments=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=false +cleanup.remove_unnecessary_nls_tags=false +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_anonymous_class_creation=false +cleanup.use_blocks=false +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_lambda=true +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup.use_type_arguments=false +cleanup_profile=_Eclipse Scout +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_Eclipse Scout +formatter_settings_version=12 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.text.custom_code_templates=