diff --git a/commons/src/main/java/org/eclipse/kapua/commons/util/xml/XmlUtil.java b/commons/src/main/java/org/eclipse/kapua/commons/util/xml/XmlUtil.java index f4e2f45932e..0460c4bdddb 100644 --- a/commons/src/main/java/org/eclipse/kapua/commons/util/xml/XmlUtil.java +++ b/commons/src/main/java/org/eclipse/kapua/commons/util/xml/XmlUtil.java @@ -15,9 +15,8 @@ import com.google.common.base.Strings; import org.apache.commons.lang.SystemUtils; -import org.eclipse.kapua.KapuaException; - import org.checkerframework.checker.nullness.qual.Nullable; +import org.eclipse.kapua.KapuaException; import org.eclipse.persistence.jaxb.JAXBContextFactory; import org.eclipse.persistence.jaxb.MarshallerProperties; import org.slf4j.Logger; @@ -418,6 +417,8 @@ private static T unmarshal(@NotNull Reader reader, @NotNull Class type, @ if (eventCollector.hasEvents()) { for (ValidationEvent valEvent : eventCollector.getEvents()) { + LOG.warn("Unmarshal Validation Event: {} - {}", valEvent.getSeverity(), valEvent.getMessage(), valEvent.getLinkedException()); + if (valEvent.getSeverity() != ValidationEvent.WARNING) { String msg = MessageFormat.format("Line {0}, Col: {1}.{2}\tError message: {3}{2}\tLinked exception message:{4}", valEvent.getLocator().getLineNumber(), diff --git a/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/JaxbContextResolver.java b/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/JaxbContextResolver.java index 034455e1512..796c0eebf7c 100644 --- a/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/JaxbContextResolver.java +++ b/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/JaxbContextResolver.java @@ -71,6 +71,7 @@ import org.eclipse.kapua.service.account.AccountCreator; import org.eclipse.kapua.service.account.AccountListResult; import org.eclipse.kapua.service.account.AccountQuery; +import org.eclipse.kapua.service.account.xml.AccountParentPathXmlAdapter; import org.eclipse.kapua.service.account.xml.AccountXmlRegistry; import org.eclipse.kapua.service.authentication.ApiKeyCredentials; import org.eclipse.kapua.service.authentication.AuthenticationCredentials; @@ -387,6 +388,7 @@ public JaxbContextResolver() { AccountCreator.class, AccountListResult.class, AccountQuery.class, + AccountParentPathXmlAdapter.class, AccountXmlRegistry.class, // Data Channel Info diff --git a/service/account/api/pom.xml b/service/account/api/pom.xml index b14fc1d14a5..ec110482145 100644 --- a/service/account/api/pom.xml +++ b/service/account/api/pom.xml @@ -28,6 +28,10 @@ org.eclipse.kapua kapua-service-api + + com.google.guava + guava + diff --git a/service/account/api/src/main/java/org/eclipse/kapua/service/account/Account.java b/service/account/api/src/main/java/org/eclipse/kapua/service/account/Account.java index 3b2c2b47ab8..1373e96dbf0 100644 --- a/service/account/api/src/main/java/org/eclipse/kapua/service/account/Account.java +++ b/service/account/api/src/main/java/org/eclipse/kapua/service/account/Account.java @@ -15,6 +15,7 @@ import org.eclipse.kapua.model.KapuaEntity; import org.eclipse.kapua.model.KapuaNamedEntity; import org.eclipse.kapua.model.xml.DateXmlAdapter; +import org.eclipse.kapua.service.account.xml.AccountParentPathXmlAdapter; import org.eclipse.kapua.service.account.xml.AccountXmlRegistry; import javax.xml.bind.annotation.XmlAccessType; @@ -71,6 +72,7 @@ default String getType() { * @since 1.0.0 */ @XmlElement(name = "parentAccountPath") + @XmlJavaTypeAdapter(AccountParentPathXmlAdapter.class) String getParentAccountPath(); /** diff --git a/service/account/api/src/main/java/org/eclipse/kapua/service/account/xml/AccountParentPathXmlAdapter.java b/service/account/api/src/main/java/org/eclipse/kapua/service/account/xml/AccountParentPathXmlAdapter.java new file mode 100644 index 00000000000..8fddcaa28e7 --- /dev/null +++ b/service/account/api/src/main/java/org/eclipse/kapua/service/account/xml/AccountParentPathXmlAdapter.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2021 Eurotech and/or its affiliates and others + * + * 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 + * + * Contributors: + * Eurotech - initial API and implementation + *******************************************************************************/ +package org.eclipse.kapua.service.account.xml; + +import com.google.common.base.Strings; +import org.eclipse.kapua.KapuaIllegalArgumentException; +import org.eclipse.kapua.locator.KapuaLocator; +import org.eclipse.kapua.model.id.KapuaIdFactory; +import org.eclipse.kapua.service.account.Account; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * {@link Account#getParentAccountPath()} {@link XmlAdapter}. + * + * @since 1.6.0 + */ +public class AccountParentPathXmlAdapter extends XmlAdapter { + + private static final KapuaLocator LOCATOR = KapuaLocator.getInstance(); + private static final KapuaIdFactory KAPUA_ID_FACTORY = LOCATOR.getFactory(KapuaIdFactory.class); + + @Override + public String marshal(String parentAccountPathLong) { + if (Strings.isNullOrEmpty(parentAccountPathLong)) { + return null; + } else { + String[] parentAccountPathLongTokens = parentAccountPathLong.substring(1).split("/"); + + List parentAccountPathBase64List = + Arrays.stream(parentAccountPathLongTokens) + .map(p -> KAPUA_ID_FACTORY.newKapuaId(new BigInteger(p)).toCompactId()) + .collect(Collectors.toList()); + + return "/" + String.join("/", parentAccountPathBase64List); + } + } + + @Override + public String unmarshal(String parentAccountPathBase64) throws KapuaIllegalArgumentException { + if (Strings.isNullOrEmpty(parentAccountPathBase64)) { + return null; + } else { + String[] parentAccountPathBase64Tokens = parentAccountPathBase64.substring(1).split("/"); + + try { + List parentAccountPathLongList = + Arrays.stream(parentAccountPathBase64Tokens) + .map(p -> KAPUA_ID_FACTORY.newKapuaId(p).toStringId()) + .collect(Collectors.toList()); + + return "/" + String.join("/", parentAccountPathLongList); + } catch (IllegalArgumentException e) { + throw new KapuaIllegalArgumentException("account.parentAccountPath", parentAccountPathBase64); + } + } + } +} diff --git a/service/account/internal/pom.xml b/service/account/internal/pom.xml index ed11d3ec713..d32888cb9c7 100644 --- a/service/account/internal/pom.xml +++ b/service/account/internal/pom.xml @@ -29,21 +29,46 @@ kapua-account-api + org.eclipse.kapua kapua-security-authorization-api + org.eclipse.kapua kapua-commons + + + + + ch.qos.logback + logback-classic + test + + + ch.qos.logback + logback-core + test + org.eclipse.kapua kapua-locator-guice test + + org.eclipse.kapua + kapua-qa-markers + test + + + junit + junit + test + diff --git a/service/account/internal/src/test/java/org/eclipse/kapua/service/account/xml/AccountParentPathXmlAdapterTest.java b/service/account/internal/src/test/java/org/eclipse/kapua/service/account/xml/AccountParentPathXmlAdapterTest.java new file mode 100644 index 00000000000..d47606b8cd5 --- /dev/null +++ b/service/account/internal/src/test/java/org/eclipse/kapua/service/account/xml/AccountParentPathXmlAdapterTest.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2021 Eurotech and/or its affiliates and others + * + * 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 + * + * Contributors: + * Eurotech - initial API and implementation + *******************************************************************************/ +package org.eclipse.kapua.service.account.xml; + +import org.eclipse.kapua.KapuaIllegalArgumentException; +import org.eclipse.kapua.qa.markers.junit.JUnitTests; +import org.junit.Assert; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import java.util.Arrays; +import java.util.List; + +@Category(JUnitTests.class) +public class AccountParentPathXmlAdapterTest { + + private static final AccountParentPathXmlAdapter XML_ADAPTER = new AccountParentPathXmlAdapter(); + + @Test + public void testMarshal() { + String parentAccountPath = "/1/2/3"; + + String marshalled = XML_ADAPTER.marshal(parentAccountPath); + + Assert.assertNotNull(marshalled); + Assert.assertEquals("/AQ/Ag/Aw", marshalled); + } + + @Test + public void testMarshalNull() { + String marshalled = XML_ADAPTER.marshal(null); + + Assert.assertNull(marshalled); + } + + @Test + public void testUnmarshal() throws KapuaIllegalArgumentException { + String parentAccountPath = "/AQ/Ag/Aw"; + + String unmarshalled = XML_ADAPTER.unmarshal(parentAccountPath); + + Assert.assertNotNull(unmarshalled); + Assert.assertEquals("/1/2/3", unmarshalled); + } + + @Test + public void testUnmarshalNull() throws KapuaIllegalArgumentException { + String unmarshalled = XML_ADAPTER.unmarshal(null); + + Assert.assertNull(unmarshalled); + } + + @Test + public void testUnmarshalInvalid() { + List parentAccountPaths = Arrays.asList("/AQ/Ag/Awwerty###", "///", "A//B", "!@#$%^&*()_"); + + for (String parentAccountPath : parentAccountPaths) { + try { + XML_ADAPTER.unmarshal(parentAccountPath); + } catch (KapuaIllegalArgumentException kapuaIllegalArgumentException) { + Assert.assertEquals("account.parentAccountPath", kapuaIllegalArgumentException.getArgumentName()); + Assert.assertEquals(parentAccountPath, kapuaIllegalArgumentException.getArgumentValue()); + } + } + } +} diff --git a/service/account/internal/src/test/resources/locator.xml b/service/account/internal/src/test/resources/locator.xml new file mode 100644 index 00000000000..79737a074cf --- /dev/null +++ b/service/account/internal/src/test/resources/locator.xml @@ -0,0 +1,22 @@ + + + + + + org.eclipse.kapua.model.id.KapuaIdFactory + + + org.eclipse.kapua.commons + + diff --git a/service/account/internal/src/test/resources/logback.xml b/service/account/internal/src/test/resources/logback.xml new file mode 100644 index 00000000000..1153dc3b425 --- /dev/null +++ b/service/account/internal/src/test/resources/logback.xml @@ -0,0 +1,28 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + +