Skip to content

Commit

Permalink
Merge pull request #35358 from gsmet/3.3.0-backports-2
Browse files Browse the repository at this point in the history
3.3.0 backports 2
  • Loading branch information
gsmet authored Aug 16, 2023
2 parents b5b6233 + 625855d commit dba2a10
Show file tree
Hide file tree
Showing 13 changed files with 265 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
*/
public final class BuildChainBuilder {

private static final String GRAPH_OUTPUT = System.getProperty("jboss.builder.graph-output");
private static final String GRAPH_OUTPUT = System.getProperty("quarkus.builder.graph-output");
static final boolean LOG_CONFLICT_CAUSING = Boolean.getBoolean("quarkus.builder.log-conflict-cause");

private final BuildStepBuilder finalStep;
Expand Down
28 changes: 28 additions & 0 deletions core/runtime/src/main/java/io/quarkus/runtime/BuilderConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.runtime;

import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.smallrye.config.ConfigMapping;

/**
* This configuration class is here to avoid warnings when using {@code -Dquarkus.builder.=...}.
*
* @see io.quarkus.builder.BuildChainBuilder
*/
@ConfigMapping(prefix = "quarkus.builder")
@ConfigRoot(phase = ConfigPhase.RUN_TIME)
public interface BuilderConfig {

/**
* Dump the graph output to a file. This is useful for debugging.
*/
Optional<String> graphOutput();

/**
* Whether to log the cause of a conflict.
*/
Optional<Boolean> logConflictCause();

}
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,19 @@ public interface MatchPredicate {

/**
* @param clazz
* @param annotations
* @param annotations The current set of (possibly transformed) annotations
* @param index
* @return {@code true} if the input arguments match the predicate,
* {@code false} otherwise
*/
boolean test(ClassInfo clazz, Collection<AnnotationInstance> annotations, IndexView index);

default MatchPredicate and(MatchPredicate other) {
MatchPredicate previous = this;
return new MatchPredicate() {
@Override
public boolean test(ClassInfo clazz, Collection<AnnotationInstance> annotations, IndexView index) {
return test(clazz, annotations, index) && other.test(clazz, annotations, index);
return previous.test(clazz, annotations, index) && other.test(clazz, annotations, index);
}
};
}
Expand Down Expand Up @@ -140,6 +141,8 @@ public Builder unremovable() {

/**
* Set a custom predicate.
* <p>
* The previous predicate (if any) is replaced.
*
* @param predicate
* @return self
Expand Down Expand Up @@ -286,7 +289,13 @@ public Builder scopeAlreadyAdded(BiConsumer<DotName, String> consumer) {
return this;
}

private Builder and(MatchPredicate other) {
/**
* The final predicate is a short-circuiting logical AND of the previous predicate (if any) and this condition.
*
* @param other
* @return self
*/
public Builder and(MatchPredicate other) {
if (matchPredicate == null) {
matchPredicate = other;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import jakarta.inject.Named;

import org.jboss.jandex.DotName;
import org.jboss.logging.Logger;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -31,9 +33,11 @@ public class AutoScopeBuildItemTest {
b.addBuildStep(new BuildStep() {
@Override
public void execute(BuildContext context) {
context.produce(AutoAddScopeBuildItem.builder().match((clazz, annotations, index) -> {
return clazz.name().toString().equals(SimpleBean.class.getName());
}).defaultScope(BuiltinScope.DEPENDENT)
context.produce(AutoAddScopeBuildItem.builder()
.match((clazz, annotations, index) -> {
return clazz.name().toString().equals(SimpleBean.class.getName());
})
.defaultScope(BuiltinScope.DEPENDENT)
.scopeAlreadyAdded((scope, reason) -> {
// We can't pass the state directly to AutoScopeBuildItemTest because it's loaded by a different classloader
Logger.getLogger("AutoScopeBuildItemTest").info(scope + ":" + reason);
Expand All @@ -43,17 +47,30 @@ public void execute(BuildContext context) {
b.addBuildStep(new BuildStep() {
@Override
public void execute(BuildContext context) {
context.produce(AutoAddScopeBuildItem.builder().match((clazz, annotations, index) -> {
return clazz.name().toString().equals(SimpleBean.class.getName());
}).defaultScope(BuiltinScope.SINGLETON).priority(10).reason("Foo!").build());
context.produce(AutoAddScopeBuildItem.builder()
.match((clazz, annotations, index) -> {
return clazz.name().toString().equals(SimpleBean.class.getName());
})
.anyMethodMatches(m -> m.hasAnnotation(PostConstruct.class))
.isAnnotatedWith(DotName.createSimple(Named.class))
.defaultScope(BuiltinScope.SINGLETON)
.priority(10)
.reason("Foo!")
.build());
}
}).produces(AutoAddScopeBuildItem.class).build();
b.addBuildStep(new BuildStep() {
@Override
public void execute(BuildContext context) {
context.produce(AutoAddScopeBuildItem.builder().match((clazz, annotations, index) -> {
return clazz.name().toString().equals(NotABean.class.getName());
}).defaultScope(BuiltinScope.SINGLETON).unremovable().build());
context.produce(AutoAddScopeBuildItem.builder()
.match((clazz, annotations, index) -> {
return clazz.name().toString().equals(NotABean.class.getName());
})
.containsAnnotations(DotName.createSimple(PostConstruct.class))
.and((clazz, annotations, index) -> annotations.isEmpty())
.defaultScope(BuiltinScope.SINGLETON)
.unremovable()
.build());
}
}).produces(AutoAddScopeBuildItem.class).build();
}).setLogRecordPredicate(log -> "AutoScopeBuildItemTest".equals(log.getLoggerName()))
Expand All @@ -76,6 +93,7 @@ public void testBeans() {
assertEquals(notABean1.ping(), Arc.container().instance(NotABean.class).get().ping());
}

@Named
static class SimpleBean {

private String id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import static io.quarkus.container.image.deployment.util.EnablementUtil.buildContainerImageNeeded;
import static io.quarkus.container.image.deployment.util.EnablementUtil.pushContainerImageNeeded;
import static io.quarkus.container.util.PathsUtil.findMainSourcesRoot;
import static io.quarkus.deployment.pkg.PackageConfig.MUTABLE_JAR;

import java.io.IOException;
import java.io.UncheckedIOException;
Expand All @@ -26,13 +25,15 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;

import com.google.cloud.tools.jib.api.CacheDirectoryCreationException;
import com.google.cloud.tools.jib.api.Containerizer;
import com.google.cloud.tools.jib.api.DockerDaemonImage;
import com.google.cloud.tools.jib.api.ImageReference;
Expand All @@ -42,6 +43,7 @@
import com.google.cloud.tools.jib.api.JibContainer;
import com.google.cloud.tools.jib.api.JibContainerBuilder;
import com.google.cloud.tools.jib.api.LogEvent;
import com.google.cloud.tools.jib.api.RegistryException;
import com.google.cloud.tools.jib.api.RegistryImage;
import com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath;
import com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer;
Expand Down Expand Up @@ -249,7 +251,7 @@ private JibContainer containerize(ContainerImageConfig containerImageConfig,
previousContextStorageSysProp = System.setProperty(OPENTELEMETRY_CONTEXT_CONTEXT_STORAGE_PROVIDER_SYS_PROP,
"default");

JibContainer container = jibContainerBuilder.containerize(containerizer);
JibContainer container = containerizeUnderLock(jibContainerBuilder, containerizer);
log.infof("%s container image %s (%s)\n",
containerImageConfig.isPushExplicitlyEnabled() ? "Pushed" : "Created",
container.getTargetImage(),
Expand Down Expand Up @@ -300,7 +302,7 @@ private Containerizer createContainerizer(ContainerImageConfig containerImageCon
}
containerizer.setToolName("Quarkus");
containerizer.setToolVersion(Version.getVersion());
containerizer.addEventHandler(LogEvent.class, (e) -> {
containerizer.addEventHandler(LogEvent.class, e -> {
if (!e.getMessage().isEmpty()) {
log.log(toJBossLoggingLevel(e.getLevel()), e.getMessage());
}
Expand All @@ -311,6 +313,29 @@ private Containerizer createContainerizer(ContainerImageConfig containerImageCon
return containerizer;
}

/**
* Wraps the containerize invocation in a synchronized block to avoid OverlappingFileLockException when running parallel jib
* builds (e.g. mvn -T2 ...).
* Each build thread uses its own augmentation CL (which is why the OverlappingFileLockException prevention in jib doesn't
* work here), so the lock object
* has to be loaded via the parent classloader so that all build threads lock the same object.
* QuarkusAugmentor was chosen semi-randomly (note: quarkus-core-deployment is visible to that parent CL, this jib extension
* is not!).
*/
private JibContainer containerizeUnderLock(JibContainerBuilder jibContainerBuilder, Containerizer containerizer)
throws InterruptedException, RegistryException, IOException, CacheDirectoryCreationException, ExecutionException {
Class<?> lockObj = getClass();
ClassLoader parentCL = getClass().getClassLoader().getParent();
try {
lockObj = parentCL.loadClass("io.quarkus.deployment.QuarkusAugmentor");
} catch (ClassNotFoundException e) {
log.warnf("Could not load io.quarkus.deployment.QuarkusAugmentor with parent classloader: %s", parentCL);
}
synchronized (lockObj) {
return jibContainerBuilder.containerize(containerizer);
}
}

private void writeOutputFiles(JibContainer jibContainer, ContainerImageJibConfig jibConfig,
OutputTargetBuildItem outputTarget) {
doWriteOutputFile(outputTarget, Paths.get(jibConfig.imageDigestFile), jibContainer.getDigest().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,16 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi
} else if (config.verifyToken) {
// unsafe HTTP method, token is required

if (!isMatchingMediaType(requestContext.getMediaType(), MediaType.APPLICATION_FORM_URLENCODED_TYPE)
&& !isMatchingMediaType(requestContext.getMediaType(), MediaType.MULTIPART_FORM_DATA_TYPE)) {
MediaType mediaType = requestContext.getMediaType();
if (!isMatchingMediaType(mediaType, MediaType.APPLICATION_FORM_URLENCODED_TYPE)
&& !isMatchingMediaType(mediaType, MediaType.MULTIPART_FORM_DATA_TYPE)) {
if (config.requireFormUrlEncoded) {
LOG.debugf("Request has the wrong media type: %s", requestContext.getMediaType().toString());
LOG.debugf("Request has the wrong media type: %s", mediaType);
requestContext.abortWith(badClientRequest());
return;
} else {
LOG.debugf("Request has the media type: %s, skipping the token verification",
requestContext.getMediaType().toString());
LOG.debugf("Request has the media type: %s, skipping the token verification",
mediaType);
return;
}
}
Expand Down Expand Up @@ -148,7 +149,16 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi
}
}

/**
* Compares if {@link MediaType} matches the expected type.
* <p>
* Note: isCompatible is taking wildcards, which is why we individually compare types and subtypes,
* so if someone sends a <code>Content-Type: *</code> it will be marked as compatible which is a problem
*/
private static boolean isMatchingMediaType(MediaType contentType, MediaType expectedType) {
if (contentType == null) {
return (expectedType == null);
}
return contentType.getType().equals(expectedType.getType())
&& contentType.getSubtype().equals(expectedType.getSubtype());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,13 @@ ReflectiveClassBuildItem registerGeneratorClassesForReflections() {
.build();
}

// Workaround for https://hibernate.atlassian.net/browse/HHH-16809
// See https://github.com/hibernate/hibernate-orm/pull/6815#issuecomment-1662197545
@BuildStep
ReflectiveClassBuildItem registerJdbcArrayTypesForReflection() {
return ReflectiveClassBuildItem
.builder(HibernateOrmTypes.JDBC_JAVA_TYPES.stream().map(d -> d.toString() + "[]").toArray(String[]::new))
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,10 @@ public void preGenAnnotationProxies(List<PersistenceUnitDescriptorBuildItem> per
// but there are plans to make deep changes to XML mapping in ORM (to rely on Jandex directly),
// so let's not waste our time on optimizations that won't be relevant in a few months.
List<String> annotationClassNames = new ArrayList<>();
for (DotName name : HibernateOrmAnnotations.JPA_MAPPING_ANNOTATIONS) {
for (DotName name : HibernateOrmTypes.JPA_MAPPING_ANNOTATIONS) {
annotationClassNames.add(name.toString());
}
for (DotName name : HibernateOrmAnnotations.HIBERNATE_MAPPING_ANNOTATIONS) {
for (DotName name : HibernateOrmTypes.HIBERNATE_MAPPING_ANNOTATIONS) {
annotationClassNames.add(name.toString());
}
reflective.produce(ReflectiveClassBuildItem.builder(annotationClassNames.toArray(new String[0]))
Expand Down Expand Up @@ -766,7 +766,7 @@ public void registerInjectServiceMethodsForReflection(CombinedIndexBuildItem ind
Set<String> classes = new HashSet<>();

// Built-in service classes; can't rely on Jandex as Hibernate ORM is not indexed by default.
HibernateOrmAnnotations.ANNOTATED_WITH_INJECT_SERVICE.stream()
HibernateOrmTypes.ANNOTATED_WITH_INJECT_SERVICE.stream()
.map(DotName::toString)
.forEach(classes::add);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import org.jboss.jandex.DotName;

public final class HibernateOrmAnnotations {
public final class HibernateOrmTypes {

private HibernateOrmAnnotations() {
private HibernateOrmTypes() {
}

public static final List<DotName> PACKAGE_ANNOTATIONS = List.of(
Expand Down Expand Up @@ -316,4 +316,41 @@ private HibernateOrmAnnotations() {
DotName.createSimple("jakarta.persistence.PreRemove"),
DotName.createSimple("jakarta.persistence.PreUpdate"));

public static final List<DotName> JDBC_JAVA_TYPES = List.of(
DotName.createSimple("java.lang.Boolean"),
DotName.createSimple("java.lang.Byte"),
DotName.createSimple("java.lang.Character"),
DotName.createSimple("java.lang.Class"),
DotName.createSimple("java.lang.Double"),
DotName.createSimple("java.lang.Float"),
DotName.createSimple("java.lang.Integer"),
DotName.createSimple("java.lang.Long"),
DotName.createSimple("java.lang.Object"),
DotName.createSimple("java.lang.Short"),
DotName.createSimple("java.lang.String"),
DotName.createSimple("java.math.BigDecimal"),
DotName.createSimple("java.math.BigInteger"),
DotName.createSimple("java.net.InetAddress"),
DotName.createSimple("java.net.URL"),
DotName.createSimple("java.sql.Blob"),
DotName.createSimple("java.sql.Clob"),
DotName.createSimple("java.sql.NClob"),
DotName.createSimple("java.time.Duration"),
DotName.createSimple("java.time.Instant"),
DotName.createSimple("java.time.LocalDate"),
DotName.createSimple("java.time.LocalDateTime"),
DotName.createSimple("java.time.LocalTime"),
DotName.createSimple("java.time.OffsetDateTime"),
DotName.createSimple("java.time.OffsetTime"),
DotName.createSimple("java.time.Year"),
DotName.createSimple("java.time.ZoneId"),
DotName.createSimple("java.time.ZoneOffset"),
DotName.createSimple("java.time.ZonedDateTime"),
DotName.createSimple("java.util.Calendar"),
DotName.createSimple("java.util.Currency"),
DotName.createSimple("java.util.Date"),
DotName.createSimple("java.util.Locale"),
DotName.createSimple("java.util.Map$Entry"),
DotName.createSimple("java.util.TimeZone"),
DotName.createSimple("java.util.UUID"));
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public final class JpaJandexScavenger {
public JpaModelBuildItem discoverModelAndRegisterForReflection() {
Collector collector = new Collector();

for (DotName packageAnnotation : HibernateOrmAnnotations.PACKAGE_ANNOTATIONS) {
for (DotName packageAnnotation : HibernateOrmTypes.PACKAGE_ANNOTATIONS) {
enlistJPAModelAnnotatedPackages(collector, packageAnnotation);
}
enlistJPAModelClasses(collector, ClassNames.JPA_ENTITY);
Expand All @@ -95,7 +95,7 @@ public JpaModelBuildItem discoverModelAndRegisterForReflection() {
enlistEmbeddedsAndElementCollections(collector);

enlistPotentialCdiBeanClasses(collector, ClassNames.CONVERTER);
for (DotName annotation : HibernateOrmAnnotations.JPA_LISTENER_ANNOTATIONS) {
for (DotName annotation : HibernateOrmTypes.JPA_LISTENER_ANNOTATIONS) {
enlistPotentialCdiBeanClasses(collector, annotation);
}

Expand Down
Loading

0 comments on commit dba2a10

Please sign in to comment.