Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ public abstract class VaadinBuildFrontendTask : DefaultTask() {
}
}
LicenseChecker.setStrictOffline(true)
val licenseRequired = BuildFrontendUtil.validateLicenses(adapter.get(), frontendDependencies)
val onlyValidateJavaImports = !isHillaUsed()
logger.info("============================ Only check Java packages? ${onlyValidateJavaImports}")
val licenseRequired = BuildFrontendUtil.validateLicenses(adapter.get(), frontendDependencies, onlyValidateJavaImports)

BuildFrontendUtil.updateBuildFile(adapter.get(), licenseRequired)
}
Expand All @@ -135,8 +137,7 @@ public abstract class VaadinBuildFrontendTask : DefaultTask() {
* @return `true` to remove created files, `false` to keep the files
*/
protected open fun cleanFrontendFiles(): Boolean {
if (FrontendUtils.isHillaUsed(BuildFrontendUtil.getGeneratedFrontendDirectory(adapter.get()),
adapter.get().classFinder)) {
if (isHillaUsed()) {
/*
* Override this to not clean generated frontend files after the
* build. For Hilla, the generated files can still be useful for
Expand All @@ -147,4 +148,8 @@ public abstract class VaadinBuildFrontendTask : DefaultTask() {
}
return adapter.get().config.cleanFrontendFiles.get()
}

private fun isHillaUsed() : Boolean = FrontendUtils.isHillaUsed(
BuildFrontendUtil.getGeneratedFrontendDirectory(adapter.get()),
adapter.get().classFinder)
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ protected void executeInternal()
}
}
LicenseChecker.setStrictOffline(true);
boolean onlyValidateJavaImports = !isHillaUsed(frontendDirectory());
boolean licenseRequired = BuildFrontendUtil.validateLicenses(this,
frontendDependencies);
frontendDependencies, onlyValidateJavaImports);

BuildFrontendUtil.updateBuildFile(this, licenseRequired);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,10 @@ private void logTroubleshootingHints(Reflector reflector, Throwable ex) {
if (ex instanceof InvocationTargetException) {
ex = ex.getCause();
}
StringBuilder errorMessage = new StringBuilder(ex.getMessage());
StringBuilder errorMessage = new StringBuilder();
if (ex.getMessage() != null) {
errorMessage.append(ex.getMessage());
}
Throwable cause = ex.getCause();
while (cause != null) {
if (cause.getMessage() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -612,11 +610,35 @@ private static void runFrontendBuildTool(PluginAdapterBase adapter,
* @param adapter
* the PluginAdapterBase
* @param frontendDependencies
* the frontend dependencies scanner
* @return {@literal true} if license validation is required because of the
* presence of commercial components, otherwise {@literal false}.
* @deprecated to be removed, used
* {@link #validateLicenses(PluginAdapterBase, FrontendDependenciesScanner, boolean)}
*/
@Deprecated(since = "24.8", forRemoval = true)
public static boolean validateLicenses(PluginAdapterBase adapter,
FrontendDependenciesScanner frontendDependencies) {
return validateLicenses(adapter, frontendDependencies, true);
}

/**
* Validate pro component licenses.
*
* @param adapter
* the PluginAdapterBase
* @param frontendDependencies
* the frontend dependencies scanner
* @param checkOnlyJavaImportedPackages
* {@code true} to only validate components imported by Java
* classes, {@code false} to validate all commercial components
* detected by the frontend build.
* @return {@literal true} if license validation is required because of the
* presence of commercial components, otherwise {@literal false}.
*/
public static boolean validateLicenses(PluginAdapterBase adapter,
FrontendDependenciesScanner frontendDependencies,
boolean checkOnlyJavaImportedPackages) {
File outputFolder = adapter.frontendOutputDirectory();

String statsJsonContent = null;
Expand Down Expand Up @@ -646,7 +668,8 @@ public static boolean validateLicenses(PluginAdapterBase adapter,
}

List<Product> commercialComponents = findCommercialFrontendComponents(
frontendDependencies, statsJsonContent);
frontendDependencies, statsJsonContent,
checkOnlyJavaImportedPackages);
commercialComponents.addAll(findCommercialJavaComponents(adapter));

for (Product component : commercialComponents) {
Expand Down Expand Up @@ -674,24 +697,36 @@ private static Logger getLogger() {
}

static List<Product> findCommercialFrontendComponents(
FrontendDependenciesScanner scanner, String statsJsonContent) {
List<Product> components = new ArrayList<>();

FrontendDependenciesScanner scanner, String statsJsonContent,
boolean checkOnlyJavaImportedPackages) {
ArrayList<Product> products = new ArrayList<>();
final JsonNode statsJson = JacksonUtils.readTree(statsJsonContent);
Set<String> usedPackages = getUsedPackages(scanner);
if (statsJson.has("cvdlModules")) {
final JsonNode cvdlModules = statsJson.get("cvdlModules");
for (String key : JacksonUtils.getKeys(cvdlModules)) {
if (!usedPackages.contains(key)) {
// If product is not used do not collect it.
continue;
}
final JsonNode cvdlModule = cvdlModules.get(key);
components.add(new Product(cvdlModule.get("name").textValue(),
cvdlModule.get("version").textValue()));
if (!statsJson.has("cvdlModules")) {
// No commercial components detected by the frontend build
return products;
}

final JsonNode cvdlModules = statsJson.get("cvdlModules");
Set<String> usedModules = new HashSet<>();
if (!checkOnlyJavaImportedPackages) {
// The bundle has been rebuilt and lists only actually used
// commercial components
usedModules.addAll(JacksonUtils.getKeys(cvdlModules));
} else {
// Only include modules that are actually used by Java classes
Set<String> usedPackages = getUsedPackages(scanner);
if (!usedPackages.isEmpty()) {
usedModules.addAll(JacksonUtils.getKeys(cvdlModules).stream()
.filter(usedPackages::contains).toList());
}
}
return components;

usedModules.stream().sorted().map(cvdlModules::get)
.map(cvdlModule -> new Product(
cvdlModule.get("name").textValue(),
cvdlModule.get("version").textValue()))
.forEach(products::add);
return products;
}

private static Set<String> getUsedPackages(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public void should_useHillaEngine_withNodeUpdater()
}

@Test
public void detectsUsedCommercialComponents() {
public void detectsUsedCommercialComponents_checkJavaImportedPackagesOnly() {

String statsJson = """
{
Expand Down Expand Up @@ -215,13 +215,61 @@ public void detectsUsedCommercialComponents() {
Mockito.when(scanner.getModules()).thenReturn(modulesMap);

List<Product> components = BuildFrontendUtil
.findCommercialFrontendComponents(scanner, statsJson);
.findCommercialFrontendComponents(scanner, statsJson, true);
// Two components are included, only one is used
Assert.assertEquals(1, components.size());
Assert.assertEquals("comm-comp", components.get(0).getName());
Assert.assertEquals("4.6.5", components.get(0).getVersion());
}

@Test
public void detectsUsedCommercialComponents_validateAllPackages_bundleRebuilt() {

String statsJson = """
{
"cvdlModules": {
"component": {
"name": "component",
"version":"1.2.3"
},
"comm-component": {
"name":"comm-comp",
"version":"4.6.5"
},
"comm-component2": {
"name":"comm-comp2",
"version":"4.6.5"
}
}
}
""";

final FrontendDependenciesScanner scanner = Mockito
.mock(FrontendDependenciesScanner.class);
Map<String, String> packages = new HashMap<>();
packages.put("comm-component", "4.6.5");
packages.put("comm-component2", "4.6.5");
packages.put("@vaadin/button", "1.2.1");
Mockito.when(scanner.getPackages()).thenReturn(packages);

List<String> modules = new ArrayList<>();
modules.add("comm-component/foo.js");
Map<ChunkInfo, List<String>> modulesMap = Collections
.singletonMap(ChunkInfo.GLOBAL, modules);
Mockito.when(scanner.getModules()).thenReturn(modulesMap);

List<Product> components = BuildFrontendUtil
.findCommercialFrontendComponents(scanner, statsJson, false);
// Two components are included, only one is used
Assert.assertEquals(3, components.size());
Assert.assertEquals("comm-comp", components.get(0).getName());
Assert.assertEquals("4.6.5", components.get(0).getVersion());
Assert.assertEquals("comm-comp2", components.get(1).getName());
Assert.assertEquals("4.6.5", components.get(1).getVersion());
Assert.assertEquals("component", components.get(2).getName());
Assert.assertEquals("1.2.3", components.get(2).getVersion());
}

@Test
public void propagateBuildInfo_tokenFileNotExisting_createTokenFile()
throws Exception {
Expand Down
Loading