From f404fe3143c00b312a917039727ae5a4eb1e2b3d Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 15 Mar 2021 11:40:53 +0000 Subject: [PATCH 1/3] Introduce the Forbidden API Maven plugin for the Hibernate ORM extension --- build-parent/pom.xml | 3 + extensions/hibernate-orm/deployment/pom.xml | 4 + extensions/hibernate-orm/pom.xml | 87 +++++++++++++++++++++ extensions/hibernate-orm/runtime/pom.xml | 4 + pom.xml | 2 + 5 files changed, 100 insertions(+) diff --git a/build-parent/pom.xml b/build-parent/pom.xml index 8befab46f807b..413561547211f 100644 --- a/build-parent/pom.xml +++ b/build-parent/pom.xml @@ -133,6 +133,9 @@ false + + 3.1 + quay.io/quarkus/ubi-quarkus-native-image:21.0.0-java11 diff --git a/extensions/hibernate-orm/deployment/pom.xml b/extensions/hibernate-orm/deployment/pom.xml index 50d056ce2e646..8e60cdce048ba 100644 --- a/extensions/hibernate-orm/deployment/pom.xml +++ b/extensions/hibernate-orm/deployment/pom.xml @@ -98,6 +98,10 @@ + + de.thetaphi + forbiddenapis + diff --git a/extensions/hibernate-orm/pom.xml b/extensions/hibernate-orm/pom.xml index 6485c44117c74..4a9abe84f6cb2 100644 --- a/extensions/hibernate-orm/pom.xml +++ b/extensions/hibernate-orm/pom.xml @@ -18,4 +18,91 @@ runtime + + + + + de.thetaphi + forbiddenapis + ${forbiddenapis-maven-plugin.version} + + + verify-forbidden-apis + + + false + + + **/*_$logger.class + + **/*_$bundle.class + + + + jdk-system-out + jdk-non-portable + + + + + jdk-unsafe-1.8 + jdk-unsafe-9 + jdk-unsafe-10 + jdk-unsafe-11 + jdk-unsafe-12 + jdk-unsafe-13 + jdk-unsafe-14 + jdk-unsafe-15 + + jdk-deprecated-1.8 + jdk-deprecated-9 + jdk-deprecated-10 + jdk-deprecated-11 + jdk-deprecated-12 + jdk-deprecated-13 + jdk-deprecated-14 + jdk-deprecated-15 + + jdk-internal-1.8 + jdk-internal-9 + jdk-internal-10 + jdk-internal-11 + jdk-internal-12 + jdk-internal-13 + jdk-internal-14 + jdk-internal-15 + + false + true + + compile + + check + + + + verify-forbidden-test-apis + + + false + true + + + jdk-unsafe + jdk-deprecated + jdk-non-portable + jdk-internal + + + test-compile + + testCheck + + + + + + + + diff --git a/extensions/hibernate-orm/runtime/pom.xml b/extensions/hibernate-orm/runtime/pom.xml index ac72fb81de814..8b316a298ebc9 100644 --- a/extensions/hibernate-orm/runtime/pom.xml +++ b/extensions/hibernate-orm/runtime/pom.xml @@ -154,6 +154,10 @@ + + de.thetaphi + forbiddenapis + diff --git a/pom.xml b/pom.xml index 966c500c3e82b..a07874feaefe6 100644 --- a/pom.xml +++ b/pom.xml @@ -123,6 +123,7 @@ true true true + true clean install @@ -146,6 +147,7 @@ true true true + true From 42916d59dbaea104a741b0d315641535c27bfdd3 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 15 Mar 2021 11:41:53 +0000 Subject: [PATCH 2/3] Fix all Forbidden API errors regarding the missing Locale on String manipulations --- .../orm/deployment/HibernateOrmProcessor.java | 23 +++++++++++-------- .../naming/CustomImplicitNamingStrategy.java | 4 +++- .../hibernate/orm/runtime/JPAConfig.java | 3 ++- .../DataSourceTenantConnectionResolver.java | 3 ++- ...ernateCurrentTenantIdentifierResolver.java | 7 ++++-- ...ibernateMultiTenantConnectionProvider.java | 11 +++++---- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java index 727124e3017a8..9f0434465e4d9 100644 --- a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java @@ -748,25 +748,28 @@ private static void producePersistenceUnitDescriptorFromConfig( .filter(i -> persistenceUnitConfig.datasource.get().equals(i.getName())) .findFirst() .orElseThrow(() -> new ConfigurationException( - String.format("The datasource '%1$s' is not configured but the persistence unit '%2$s' uses it." - + " To solve this, configure datasource '%1$s'." - + " Refer to https://quarkus.io/guides/datasource for guidance.", + String.format(Locale.ROOT, + "The datasource '%1$s' is not configured but the persistence unit '%2$s' uses it." + + " To solve this, configure datasource '%1$s'." + + " Refer to https://quarkus.io/guides/datasource for guidance.", persistenceUnitConfig.datasource.get(), persistenceUnitName))); dataSource = persistenceUnitConfig.datasource.get(); } else { if (!PersistenceUnitUtil.isDefaultPersistenceUnit(persistenceUnitName)) { // if it's not the default persistence unit, we mandate a datasource to prevent common errors throw new ConfigurationException( - String.format("Datasource must be defined for persistence unit '%s'.", persistenceUnitName)); + String.format(Locale.ROOT, "Datasource must be defined for persistence unit '%s'.", + persistenceUnitName)); } jdbcDataSource = jdbcDataSources.stream() .filter(i -> i.isDefault()) .findFirst() .orElseThrow(() -> new ConfigurationException( - String.format("The default datasource is not configured but the persistence unit '%s' uses it." - + " To solve this, configure the default datasource." - + " Refer to https://quarkus.io/guides/datasource for guidance.", + String.format(Locale.ROOT, + "The default datasource is not configured but the persistence unit '%s' uses it." + + " To solve this, configure the default datasource." + + " Refer to https://quarkus.io/guides/datasource for guidance.", persistenceUnitName))); dataSource = DataSourceUtil.DEFAULT_DATASOURCE_NAME; } @@ -850,7 +853,7 @@ private static void producePersistenceUnitDescriptorFromConfig( persistenceUnitConfig.query.queryPlanCacheMaxSize)); descriptor.getProperties().setProperty(AvailableSettings.DEFAULT_NULL_ORDERING, - persistenceUnitConfig.query.defaultNullOrdering.name().toLowerCase()); + persistenceUnitConfig.query.defaultNullOrdering.name().toLowerCase(Locale.ROOT)); // JDBC persistenceUnitConfig.jdbc.timezone.ifPresent( @@ -1040,7 +1043,7 @@ private static Map> getModelClassesAndPackagesPerPersistence String candidatePersistenceUnitName = candidatePersistenceUnitEntry.getKey(); Set candidatePersistenceUnitPackages = candidatePersistenceUnitEntry.getValue().packages - .orElseThrow(() -> new ConfigurationException(String.format( + .orElseThrow(() -> new ConfigurationException(String.format(Locale.ROOT, "Packages must be configured for persistence unit '%s'.", candidatePersistenceUnitName))); for (String packageName : candidatePersistenceUnitPackages) { @@ -1099,7 +1102,7 @@ private static Map> getModelClassesAndPackagesPerPersistence } if (!modelClassesWithPersistenceUnitAnnotations.isEmpty()) { - throw new IllegalStateException(String.format( + throw new IllegalStateException(String.format(Locale.ROOT, "@PersistenceUnit annotations are not supported at the class level on model classes:\n\t- %s\nUse the `.packages` configuration property or package-level annotations instead.", String.join("\n\t- ", modelClassesWithPersistenceUnitAnnotations))); } diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/naming/CustomImplicitNamingStrategy.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/naming/CustomImplicitNamingStrategy.java index 7687491a12678..3b699303d271c 100644 --- a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/naming/CustomImplicitNamingStrategy.java +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/naming/CustomImplicitNamingStrategy.java @@ -1,5 +1,7 @@ package io.quarkus.hibernate.orm.naming; +import java.util.Locale; + import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.ImplicitEntityNameSource; import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl; @@ -7,7 +9,7 @@ public class CustomImplicitNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl { @Override public Identifier determinePrimaryTableName(ImplicitEntityNameSource source) { - return toIdentifier("TBL_" + source.getEntityNaming().getEntityName().replace('.', '_').toUpperCase(), + return toIdentifier("TBL_" + source.getEntityNaming().getEntityName().replace('.', '_').toUpperCase(Locale.ROOT), source.getBuildingContext()); } } diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java index a47169ef6777d..a905ebda8648a 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java @@ -2,6 +2,7 @@ import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -54,7 +55,7 @@ public EntityManagerFactory getEntityManagerFactory(String unitName) { if (lazyPersistenceUnit == null) { throw new IllegalArgumentException( - String.format("Unable to find an EntityManagerFactory for persistence unit '%s'", unitName)); + String.format(Locale.ROOT, "Unable to find an EntityManagerFactory for persistence unit '%s'", unitName)); } return lazyPersistenceUnit.get(); diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/DataSourceTenantConnectionResolver.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/DataSourceTenantConnectionResolver.java index 4ccf32662fed7..0fa9b0114e041 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/DataSourceTenantConnectionResolver.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/DataSourceTenantConnectionResolver.java @@ -2,6 +2,7 @@ import java.sql.Connection; import java.sql.SQLException; +import java.util.Locale; import javax.enterprise.inject.Default; @@ -55,7 +56,7 @@ public ConnectionProvider resolve(String tenantId) { multiTenancySchemaDataSourceName); if (dataSource == null) { throw new IllegalStateException( - String.format("No instance of datasource found for persistence unit '%1$s' and tenant '%2$s'", + String.format(Locale.ROOT, "No instance of datasource found for persistence unit '%1$s' and tenant '%2$s'", persistenceUnitName, tenantId)); } if (multiTenancyStrategy == MultiTenancyStrategy.SCHEMA) { diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java index efa048cfe696d..195eafbd21f04 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java @@ -1,5 +1,7 @@ package io.quarkus.hibernate.orm.runtime.tenant; +import java.util.Locale; + import javax.enterprise.inject.Default; import org.hibernate.context.spi.CurrentTenantIdentifierResolver; @@ -60,8 +62,9 @@ private static TenantResolver tenantResolver(String persistenceUnitName) { new PersistenceUnitLiteral(persistenceUnitName)); } if (!resolverInstance.isAvailable()) { - throw new IllegalStateException(String.format("No instance of %1$s was found for persistence unit %2$s. " - + "You need to create an implementation for this interface to allow resolving the current tenant identifier.", + throw new IllegalStateException(String.format(Locale.ROOT, + "No instance of %1$s was found for persistence unit %2$s. " + + "You need to create an implementation for this interface to allow resolving the current tenant identifier.", TenantResolver.class.getSimpleName(), persistenceUnitName)); } return resolverInstance.get(); diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateMultiTenantConnectionProvider.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateMultiTenantConnectionProvider.java index ea22a78637761..ddf8000db0f69 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateMultiTenantConnectionProvider.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateMultiTenantConnectionProvider.java @@ -1,5 +1,6 @@ package io.quarkus.hibernate.orm.runtime.tenant; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -68,8 +69,9 @@ private static ConnectionProvider resolveConnectionProvider(String persistenceUn } if (!instance.isAvailable()) { throw new IllegalStateException( - String.format("No instance of %1$s was found for persistence unit %2$s. " - + "You need to create an implementation for this interface to allow resolving the current tenant connection.", + String.format( + Locale.ROOT, "No instance of %1$s was found for persistence unit %2$s. " + + "You need to create an implementation for this interface to allow resolving the current tenant connection.", TenantConnectionResolver.class.getSimpleName(), persistenceUnitName)); } TenantConnectionResolver resolver = instance.get(); @@ -95,8 +97,9 @@ private static TenantResolver tenantResolver(String persistenceUnitName) { new PersistenceUnitLiteral(persistenceUnitName)); } if (!resolverInstance.isAvailable()) { - throw new IllegalStateException(String.format("No instance of %1$s was found for persistence unit %2$s. " - + "You need to create an implementation for this interface to allow resolving the current tenant identifier.", + throw new IllegalStateException(String.format(Locale.ROOT, + "No instance of %1$s was found for persistence unit %2$s. " + + "You need to create an implementation for this interface to allow resolving the current tenant identifier.", TenantResolver.class.getSimpleName(), persistenceUnitName)); } return resolverInstance.get(); From 3354337bec6f4276572da381a86e3e52cdc0f431 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 15 Mar 2021 11:42:30 +0000 Subject: [PATCH 3/3] Fix Forbidden API warning about Class#newInstance() being deprecated in Java 15 --- .../orm/runtime/boot/FastBootMetadataBuilder.java | 5 +++-- .../orm/runtime/boot/RecordableBootstrapFactory.java | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java index 44ea98d385395..05353c01bffe4 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java @@ -19,6 +19,7 @@ import static org.hibernate.jpa.AvailableSettings.COLLECTION_CACHE_PREFIX; import static org.hibernate.jpa.AvailableSettings.PERSISTENCE_UNIT_NAME; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -603,8 +604,8 @@ private void applyMetadataBuilderContributor() { if (metadataBuilderContributorImplClass != null) { try { - metadataBuilderContributor = metadataBuilderContributorImplClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + metadataBuilderContributor = metadataBuilderContributorImplClass.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { throw new IllegalArgumentException("The MetadataBuilderContributor class [" + metadataBuilderContributorImplClass + "] could not be instantiated!", e); } diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/RecordableBootstrapFactory.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/RecordableBootstrapFactory.java index 26ddc5648c327..13dce20f0ac6b 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/RecordableBootstrapFactory.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/RecordableBootstrapFactory.java @@ -1,5 +1,7 @@ package io.quarkus.hibernate.orm.runtime.boot; +import java.lang.reflect.InvocationTargetException; + import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl; @@ -51,9 +53,10 @@ private static InitialInitiatorListProvider initReactiveListProviderMaybe() { //Use reflection as we don't want the Hibernate ORM extension to depend on the Hibernate Reactive extension: final Class forName = Class .forName("io.quarkus.hibernate.reactive.runtime.boot.registry.ReactiveHibernateInitiatorListProvider"); - final Object o = forName.newInstance(); + final Object o = forName.getDeclaredConstructor().newInstance(); return (InitialInitiatorListProvider) o; - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException + | InvocationTargetException e) { //Be silent as this is a static initializer: most likely the Hibernate Reactive extension is //not on the classpath, which implies we won't need this. return null;