diff --git a/flow-polymer-template/src/main/java/com/vaadin/flow/component/polymertemplate/PolymerTemplate.java b/flow-polymer-template/src/main/java/com/vaadin/flow/component/polymertemplate/PolymerTemplate.java index 9f7cf25ce62..adcf8d1b9df 100644 --- a/flow-polymer-template/src/main/java/com/vaadin/flow/component/polymertemplate/PolymerTemplate.java +++ b/flow-polymer-template/src/main/java/com/vaadin/flow/component/polymertemplate/PolymerTemplate.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.polymertemplate; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; import com.vaadin.flow.component.Component; @@ -22,6 +23,7 @@ import com.vaadin.flow.server.VaadinService; import com.vaadin.flow.server.Version; import com.vaadin.flow.templatemodel.TemplateModel; +import com.vaadin.pro.licensechecker.BuildType; import com.vaadin.pro.licensechecker.LicenseChecker; /** @@ -53,11 +55,11 @@ public abstract class PolymerTemplate extends AbstractTemplate implements Template { + private static final AtomicBoolean licenseChecked = new AtomicBoolean( + false); + static { UsageStatistics.markAsUsed("flow/PolymerTemplate", null); - - LicenseChecker.checkLicenseFromStaticBlock("flow-polymer-template", - Version.getFullVersion(), null); } /** @@ -90,6 +92,14 @@ protected PolymerTemplate(TemplateParser parser, VaadinService service) { + "instantiation logic should be protected by a session lock." + "Call your logic inside the UI::access method."); } + + if (!service.getDeploymentConfiguration().isProductionMode() + && !licenseChecked.get()) { + LicenseChecker.checkLicense("flow-polymer-template", + Version.getFullVersion(), BuildType.DEVELOPMENT); + licenseChecked.compareAndSet(false, true); + } + TemplateInitializer templateInitializer = new TemplateInitializer(this, parser, service); templateInitializer.initChildElements(); diff --git a/flow-polymer-template/src/test/java/com/vaadin/flow/component/polymertemplate/PolymerTemplateTest.java b/flow-polymer-template/src/test/java/com/vaadin/flow/component/polymertemplate/PolymerTemplateTest.java index 1c36ebd00ee..356947ebb7b 100644 --- a/flow-polymer-template/src/test/java/com/vaadin/flow/component/polymertemplate/PolymerTemplateTest.java +++ b/flow-polymer-template/src/test/java/com/vaadin/flow/component/polymertemplate/PolymerTemplateTest.java @@ -9,6 +9,7 @@ package com.vaadin.flow.component.polymertemplate; import java.io.Serializable; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -16,6 +17,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -25,6 +27,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.mockito.MockedStatic; import org.mockito.Mockito; import com.vaadin.flow.component.Component; @@ -48,6 +51,8 @@ import com.vaadin.flow.server.VaadinSession; import com.vaadin.flow.templatemodel.AllowClientUpdates; import com.vaadin.flow.templatemodel.TemplateModel; +import com.vaadin.pro.licensechecker.BuildType; +import com.vaadin.pro.licensechecker.LicenseChecker; import elemental.json.JsonArray; import elemental.json.JsonObject; @@ -131,6 +136,10 @@ public static class TestPolymerTemplate public TestPolymerTemplate() { super(new SimpleTemplateParser()); } + + public TestPolymerTemplate(VaadinService service) { + super(new SimpleTemplateParser(), service); + } } @Tag(TAG) @@ -985,6 +994,63 @@ public void initModel_sendUpdatableProperties() { Assert.assertTrue(props.contains("title")); } + @Test + public void licenseCheck_devMode_licenseCheckedOnce() + throws NoSuchFieldException, IllegalAccessException { + Field licenseChecked = PolymerTemplate.class + .getDeclaredField("licenseChecked"); + licenseChecked.setAccessible(true); + AtomicBoolean licenseCheckedHolder = (AtomicBoolean) licenseChecked + .get(null); + boolean licenseCheckedInitValue = licenseCheckedHolder.get(); + + try (MockedStatic checker = Mockito + .mockStatic(LicenseChecker.class)) { + AtomicInteger counter = new AtomicInteger(0); + checker.when(() -> LicenseChecker.checkLicense(Mockito.anyString(), + Mockito.anyString(), Mockito.eq(BuildType.DEVELOPMENT))) + .then(ignore -> counter.incrementAndGet()); + + DeploymentConfiguration configuration = Mockito + .mock(DeploymentConfiguration.class); + Mockito.when(configuration.isProductionMode()).thenReturn(false); + + VaadinService service = Mockito.mock(VaadinService.class); + Mockito.when(service.getDeploymentConfiguration()) + .thenReturn(configuration); + + licenseCheckedHolder.set(false); + new TestPolymerTemplate(service); + Assert.assertEquals(1, counter.get()); + new TestPolymerTemplate(service); + Assert.assertEquals(1, counter.get()); + } finally { + licenseCheckedHolder.compareAndSet(true, licenseCheckedInitValue); + } + } + + @Test + public void licenseCheck_prodMode_licenseNotChecked() { + try (MockedStatic checker = Mockito + .mockStatic(LicenseChecker.class)) { + AtomicInteger counter = new AtomicInteger(0); + checker.when(() -> LicenseChecker.checkLicense(Mockito.anyString(), + Mockito.anyString(), Mockito.eq(BuildType.DEVELOPMENT))) + .then(ignore -> counter.incrementAndGet()); + + DeploymentConfiguration configuration = Mockito + .mock(DeploymentConfiguration.class); + Mockito.when(configuration.isProductionMode()).thenReturn(true); + + VaadinService service = Mockito.mock(VaadinService.class); + Mockito.when(service.getDeploymentConfiguration()) + .thenReturn(configuration); + + new TestPolymerTemplate(service); + Assert.assertEquals(0, counter.get()); + } + } + private void doParseTemplate_hasIdChild_childIsRegisteredInFeature( IdChildTemplate template) { VirtualChildrenList feature = template.getStateNode()