Skip to content

Commit

Permalink
More changes to default content type
Browse files Browse the repository at this point in the history
Signed-off-by: Phillip Kruger <[email protected]>
  • Loading branch information
phillip-kruger committed Oct 24, 2023
1 parent 6d4eecf commit 8060843
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 14 deletions.
8 changes: 8 additions & 0 deletions core/src/main/java/io/smallrye/openapi/api/OpenApiConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ default Optional<String[]> getDefaultPrimitivesConsumes() {
return getConfigValue(OpenApiConstants.DEFAULT_CONSUMES_PRIMITIVES, String[].class, Optional::of, Optional::empty);
}

default Optional<String[]> getDefaultStreamingProduces() {
return getConfigValue(OpenApiConstants.DEFAULT_PRODUCES_STREAMING, String[].class, Optional::of, Optional::empty);
}

default Optional<String[]> getDefaultStreamingConsumes() {
return getConfigValue(OpenApiConstants.DEFAULT_CONSUMES_STREAMING, String[].class, Optional::of, Optional::empty);
}

default Optional<Boolean> allowNakedPathParameter() {
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import org.jboss.jandex.DotName;
Expand All @@ -27,6 +28,7 @@ public class JDKConstants {
public static final DotName DOTNAME_OPTIONAL_INT = DotName.createSimple(OptionalInt.class.getName());
public static final DotName DOTNAME_OPTIONAL_LONG = DotName.createSimple(OptionalLong.class.getName());
public static final DotName COMPLETION_STAGE_NAME = DotName.createSimple(CompletionStage.class.getName());
public static final DotName COMPLETABLE_FUTURE_NAME = DotName.createSimple(CompletableFuture.class.getName());

public static final Set<DotName> DOTNAME_OPTIONALS = Collections
.unmodifiableSet(new HashSet<>(Arrays.asList(DOTNAME_OPTIONAL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public final class OpenApiConstants {
public static final String DEFAULT_CONSUMES = SMALLRYE_PREFIX + "defaultConsumes";
public static final String DEFAULT_PRODUCES_PRIMITIVES = SMALLRYE_PREFIX + "defaultPrimitivesProduces";
public static final String DEFAULT_CONSUMES_PRIMITIVES = SMALLRYE_PREFIX + "defaultPrimitivesConsumes";
public static final String DEFAULT_PRODUCES_STREAMING = SMALLRYE_PREFIX + "defaultStreamingProduces";
public static final String DEFAULT_CONSUMES_STREAMING = SMALLRYE_PREFIX + "defaultStreamingConsumes";

public static final String MAXIMUM_STATIC_FILE_SIZE = SMALLRYE_PREFIX + "maximumStaticFileSize";
public static final String AUTO_INHERITANCE = SMALLRYE_PREFIX + "auto-inheritance";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package io.smallrye.openapi.runtime.scanner.spi;

import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.microprofile.openapi.models.Extensible;
import org.jboss.jandex.DotName;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.Type;

import io.smallrye.openapi.api.OpenApiConfig;
Expand All @@ -22,6 +30,32 @@
public abstract class AbstractAnnotationScanner implements AnnotationScanner {
private static final String EMPTY = "";

private static final Set<DotName> PRIMITIVE_OBJECTS = new HashSet<>();
private static final Set<DotName> STREAM_OBJECTS = new HashSet<>();

static {
PRIMITIVE_OBJECTS.add(DotName.createSimple(String.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(Integer.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(Short.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(Long.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(Float.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(Double.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(Boolean.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(Character.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(BigDecimal.class));
PRIMITIVE_OBJECTS.add(DotName.createSimple(BigInteger.class));

STREAM_OBJECTS.add(DotName.createSimple(File.class));
STREAM_OBJECTS.add(DotName.createSimple(Path.class));
STREAM_OBJECTS.add(DotName.createSimple(InputStream.class));
STREAM_OBJECTS.add(DotName.createSimple(Reader.class));
STREAM_OBJECTS.add(DotName.createSimple(Byte.class));
STREAM_OBJECTS.add(DotName.createSimple(byte[].class));
STREAM_OBJECTS.add(DotName.createSimple("io.vertx.core.file.AsyncFile"));
STREAM_OBJECTS.add(DotName.createSimple("io.vertx.core.buffer.Buffer"));

}

protected String currentAppPath = EMPTY;
private String contextRoot = EMPTY;

Expand Down Expand Up @@ -105,19 +139,51 @@ private static boolean profileIncluded(OpenApiConfig config, Set<String> profile
}

public String[] getDefaultConsumes(AnnotationScannerContext context, MethodInfo methodInfo) {
return context.getConfig().getDefaultConsumes().orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
if (methodInfo.parametersCount() > 0) {
List<MethodParameterInfo> parameters = methodInfo.parameters();
for (MethodParameterInfo mip : parameters) {
if (isRequestBody(mip)) {
if (isStreaming(mip.type())) {
return context.getConfig().getDefaultStreamingConsumes()
.orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
} else if (isPrimimive(mip.type())) {
return context.getConfig().getDefaultPrimitivesConsumes()
.orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
}
return context.getConfig().getDefaultConsumes().orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
}
}
}

return new String[] {};
}

public String[] getDefaultProduces(AnnotationScannerContext context, MethodInfo methodInfo) {
if (isPrimimive(methodInfo.returnType())) {
if (isStreaming(methodInfo.returnType())) {
return context.getConfig().getDefaultStreamingProduces().orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
} else if (isPrimimive(methodInfo.returnType())) {
return context.getConfig().getDefaultPrimitivesProduces().orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
}
return context.getConfig().getDefaultProduces().orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
}

private boolean isPrimimive(Type type) {
return type.kind().equals(Type.Kind.PRIMITIVE)
|| type.name().equals(DotName.createSimple(String.class))
|| (TypeUtil.isWrappedType(type) && isPrimimive(TypeUtil.unwrapType(type)));
if (type != null) {
return type.kind().equals(Type.Kind.PRIMITIVE)
|| PRIMITIVE_OBJECTS.contains(type.name())
|| (isWrapperType(type) && isPrimimive(unwrapType(type)))
|| (TypeUtil.isWrappedType(type) && isPrimimive(TypeUtil.unwrapType(type)));
}
return false;
}

private boolean isStreaming(Type type) {
if (type != null) {
return (type.kind().equals(Type.Kind.PRIMITIVE) && type.kind().equals(byte.class))
|| STREAM_OBJECTS.contains(type.name())
|| (isWrapperType(type) && isStreaming(unwrapType(type)))
|| (TypeUtil.isWrappedType(type) && isStreaming(TypeUtil.unwrapType(type)));
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;
Expand Down Expand Up @@ -990,7 +991,7 @@ && getConsumes(context) != null) {
}

if (schema != null) {
ModelUtil.setRequestBodySchema(requestBody, schema, getConsumes(context));
ModelUtil.setRequestBodySchema(requestBody, schema, getConsumesForRequestBody(context));
}

if (requestBody.getRequired() == null && TypeUtil.isOptional(requestBodyType)) {
Expand All @@ -1015,6 +1016,18 @@ default String[] getConsumes(final AnnotationScannerContext context) {
return currentConsumes;
}

default String[] getConsumesForRequestBody(final AnnotationScannerContext context) {
String[] currentConsumes = context.getCurrentConsumes();
if (currentConsumes == null || currentConsumes.length == 0) {
currentConsumes = context.getDefaultConsumes();
}
return currentConsumes;
}

default boolean isRequestBody(MethodParameterInfo mip) {
return mip.annotations().isEmpty();
}

/**
* Go through the method parameters looking for one that is not a Kotlin Continuation,
* is not annotated with a jax-rs/spring annotation, and is not a known path parameter.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class AnnotationScannerContext {
private final Set<Type> jsonViews = new LinkedHashSet<>();
private String[] currentConsumes;
private String[] currentProduces;
private String[] defaultConsumes;
private String[] defaultProduces;
private Optional<AnnotationScanner> currentScanner = Optional.empty();
private final SchemaRegistry schemaRegistry;
private final JavaSecurityProcessor javaSecurityProcessor;
Expand Down Expand Up @@ -149,6 +151,22 @@ public void setCurrentProduces(String[] currentProduces) {
this.currentProduces = currentProduces;
}

public String[] getDefaultConsumes() {
return defaultConsumes;
}

public void setDefaultConsumes(String[] defaultConsumes) {
this.defaultConsumes = defaultConsumes;
}

public String[] getDefaultProduces() {
return defaultProduces;
}

public void setDefaultProduces(String[] defaultProduces) {
this.defaultProduces = defaultProduces;
}

public Optional<AnnotationScanner> getCurrentScanner() {
return currentScanner;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ public class TypeUtil {

wrapperTypes.addAll(JaxbConstants.JAXB_ELEMENT);
wrapperTypes.add(MutinyConstants.UNI_TYPE.name());
wrapperTypes.add(JDKConstants.COMPLETION_STAGE_NAME);
wrapperTypes.add(JDKConstants.COMPLETABLE_FUTURE_NAME);
}

private static void indexOptional(Indexer indexer, String className, ClassLoader contextLoader) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,12 @@ private void processResourceMethod(final AnnotationScannerContext context,

// Figure out the current @Produces and @Consumes (if any)
String[] defaultConsumes = getDefaultConsumes(context, method);
context.setCurrentConsumes(getMediaTypes(context, method, JaxRsConstants.CONSUMES, defaultConsumes));
context.setDefaultConsumes(defaultConsumes);
context.setCurrentConsumes(getMediaTypes(context, method, JaxRsConstants.CONSUMES, defaultConsumes).orElse(null));

String[] defaultProduces = getDefaultProduces(context, method);
context.setCurrentProduces(getMediaTypes(context, method, JaxRsConstants.PRODUCES, defaultProduces));
context.setDefaultProduces(defaultProduces);
context.setCurrentProduces(getMediaTypes(context, method, JaxRsConstants.PRODUCES, defaultProduces).orElse(null));

// Process any @Operation annotation
Optional<Operation> maybeOperation = processOperation(context, resourceClass, method);
Expand Down Expand Up @@ -541,16 +543,15 @@ static List<Parameter> excludeOperationParameters(List<Parameter> locatorParams,
* not found, search for {@code annotationName} on {@code resourceMethod}'s containing class or any
* of its super-classes or interfaces.
*/
static String[] getMediaTypes(AnnotationScannerContext context, MethodInfo resourceMethod, Set<DotName> annotationName,
String[] defaultValue) {
static Optional<String[]> getMediaTypes(AnnotationScannerContext context, MethodInfo resourceMethod,
Set<DotName> annotationName, String[] defaultValue) {

return context.getAugmentedIndex().ancestry(resourceMethod).entrySet()
.stream()
.map(e -> getMediaTypeAnnotation(e.getKey(), e.getValue(), annotationName))
.filter(Objects::nonNull)
.map(annotation -> mediaTypeValue(annotation, defaultValue))
.findFirst()
.orElse(null);
.findFirst();
}

static AnnotationInstance getMediaTypeAnnotation(ClassInfo clazz, MethodInfo method, Set<DotName> annotationName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.Type;

import io.smallrye.openapi.api.constants.OpenApiConstants;
Expand Down Expand Up @@ -290,9 +291,11 @@ private void processControllerMethod(final AnnotationScannerContext context,

// Figure out the current @Produces and @Consumes (if any)
String[] defaultConsumes = getDefaultConsumes(context, method);
context.setDefaultConsumes(defaultConsumes);
context.setCurrentConsumes(getMediaTypes(method, SpringConstants.MAPPING_CONSUMES, defaultConsumes).orElse(null));

String[] defaultProduces = getDefaultProduces(context, method);
context.setDefaultProduces(defaultProduces);
context.setCurrentProduces(getMediaTypes(method, SpringConstants.MAPPING_PRODUCES, defaultProduces).orElse(null));

// Process any @Operation annotation
Expand Down Expand Up @@ -383,10 +386,12 @@ static Optional<String[]> getMediaTypes(MethodInfo resourceMethod, String proper
if (annotationValue != null) {
return Optional.of(annotationValue.asStringArray());
}

return Optional.of(defaultValue);
}

return Optional.empty();
}

public boolean isRequestBody(MethodParameterInfo mip) {
return mip.annotations().isEmpty() || Annotations.hasAnnotation(mip, SpringConstants.REQUEST_BODY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ private void processRouteMethods(final AnnotationScannerContext context,
locatorPathParameters)));
}

@Override
public String[] getDefaultConsumes(AnnotationScannerContext context, MethodInfo methodInfo) {
return context.getConfig().getDefaultConsumes().orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
}

@Override
public String[] getDefaultProduces(AnnotationScannerContext context, MethodInfo methodInfo) {
return context.getConfig().getDefaultProduces().orElseGet(OpenApiConstants.DEFAULT_MEDIA_TYPES);
}

/**
* Process a single Vert.x method to produce an OpenAPI Operation.
*
Expand All @@ -234,9 +244,11 @@ private void processRouteMethod(final AnnotationScannerContext context,

// Figure out the current @Produces and @Consumes (if any)
String[] defaultConsumes = getDefaultConsumes(context, method);
context.setDefaultConsumes(defaultConsumes);
context.setCurrentConsumes(getMediaTypes(method, VertxConstants.ROUTE_CONSUMES,
defaultConsumes).orElse(null));
String[] defaultProduces = getDefaultProduces(context, method);
context.setDefaultProduces(defaultProduces);
context.setCurrentProduces(getMediaTypes(method, VertxConstants.ROUTE_PRODUCES,
defaultProduces).orElse(null));

Expand Down

0 comments on commit 8060843

Please sign in to comment.