Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic Annotation value handling and Support for DataSourceDefinition #94

Merged
merged 2 commits into from
Nov 25, 2024
Merged
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
52 changes: 52 additions & 0 deletions core/src/main/java/org/wildfly/glow/AnnotationFieldValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/
jfdenise marked this conversation as resolved.
Show resolved Hide resolved
package org.wildfly.glow;

/**
*
* @author jdenise
*/
public class AnnotationFieldValue {

private final String annotation;
private final String fieldName;
private final String fieldValue;
private final Layer layer;

public AnnotationFieldValue(String annotation, String fieldName, String fieldValue, Layer layer) {
this.annotation = annotation;
this.fieldName = fieldName;
this.fieldValue = fieldValue;
this.layer = layer;
}

/**
* @return the annotation
*/
public String getAnnotation() {
return annotation;
}

/**
* @return the fieldName
*/
public String getFieldName() {
return fieldName;
}

/**
* @return the fieldValue
*/
public String getFieldValue() {
return fieldValue;
}

/**
* @return the layer
*/
public Layer getLayer() {
return layer;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.wildfly.glow;


public class DataSourceDefinitionInfo {
private final String name;
private final String url;
private final String className;
private final Layer driverLayer;
public DataSourceDefinitionInfo(String name, String url, String className, Layer driverLayer) {
this.name = name;
this.url = url;
this.className = className;
this.driverLayer = driverLayer;
}

/**
* @return the name
*/
public String getName() {
return name;
}

/**
* @return the url
*/
public String getUrl() {
return url;
}

/**
* @return the className
*/
public String getClassName() {
return className;
}

/**
* @return the driverLayer
*/
public Layer getDriverLayer() {
return driverLayer;
}
}
44 changes: 43 additions & 1 deletion core/src/main/java/org/wildfly/glow/DeploymentScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
Expand Down Expand Up @@ -139,7 +140,7 @@ public void scan(LayerMapping mapping, Set<Layer> layers, Map<String, Layer> all
}
}

errorSession.collectEndOfScanErrors(verbose, ctx.resourceInjectionJndiInfos, ctx.contextLookupInfos, ctx.allClasses);
errorSession.collectEndOfScanErrors(verbose, ctx.resourceInjectionJndiInfos, ctx.contextLookupInfos, ctx.dataSourceDefinitionInfos, ctx.allClasses);
}

private void scan(DeploymentScanContext ctx) throws Exception {
Expand Down Expand Up @@ -193,6 +194,34 @@ private void scanAnnotations(DeploymentScanContext ctx) throws IOException {
}
}
}
Map<String, List<AnnotationFieldValue>> fields = ctx.mapping.getAnnotationFieldValues().get(ai.name().toString());
if (fields != null) {
Layer foundLayer = null;
for(Entry<String, List<AnnotationFieldValue>> f : fields.entrySet()) {
String val = getAnnotationValue(ai, f.getKey());
if (val != null) {
List<AnnotationFieldValue> lstFields = f.getValue();
for (AnnotationFieldValue fv : lstFields) {
if (Utils.isPattern(fv.getFieldValue())) {
Pattern p = Pattern.compile(fv.getFieldValue());
if (p.matcher(val).matches()) {
foundLayer = fv.getLayer();
LayerMapping.addRule(LayerMapping.RULE.ANNOTATION_VALUE, foundLayer, ai.name().toString() + "_" + f.getKey() + "=" + fv.getFieldValue());
ctx.layers.add(fv.getLayer());
}
} else {
if (val.equals(fv.getFieldValue())) {
foundLayer = fv.getLayer();
LayerMapping.addRule(LayerMapping.RULE.ANNOTATION_VALUE, foundLayer, ai.name().toString() + "_" + f.getKey() + "=" + fv.getFieldValue());
ctx.layers.add(fv.getLayer());
}
}
}
}
}
// DataSourceDefinition are only added based on layers discovered in the above nested loop.
handleDataSourceDefinitionAnnotations(ai, ctx, foundLayer);
jfdenise marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
Expand Down Expand Up @@ -260,6 +289,18 @@ private void handleResourceInjectionAnnotations(AnnotationInstance annotationIns
}
}

private void handleDataSourceDefinitionAnnotations(AnnotationInstance annotationInstance, DeploymentScanContext ctx, Layer foundLayer) {
if (annotationInstance.name().toString().equals("jakarta.annotation.sql.DataSourceDefinition")) {
String name = getAnnotationValue(annotationInstance, "name");
String url = getAnnotationValue(annotationInstance, "url");
String className = getAnnotationValue(annotationInstance, "className");
if (name != null) {
DataSourceDefinitionInfo di = new DataSourceDefinitionInfo(name, url, className, foundLayer);
ctx.dataSourceDefinitionInfos.put(name, di);
}
}
}

private boolean isSetter(MethodInfo methodInfo) {
return methodInfo.name().startsWith("set") && methodInfo.parameterTypes().size() == 1;
}
Expand Down Expand Up @@ -840,6 +881,7 @@ static class DeploymentScanContext {
private final ErrorIdentificationSession errorSession;
private final Set<String> allClasses = new HashSet<>();
private final Map<String, ResourceInjectionJndiInfo> resourceInjectionJndiInfos = new HashMap<>();
private final Map<String, DataSourceDefinitionInfo> dataSourceDefinitionInfos = new HashMap<>();
public Set<ContextLookupInfo> contextLookupInfos = new HashSet<>();

private DeploymentScanContext(LayerMapping mapping, Set<Layer> layers, Map<String, Layer> allLayers, ErrorIdentificationSession errorSession) {
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/java/org/wildfly/glow/LayerMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
Expand All @@ -35,6 +36,7 @@ public enum RULE {
ADD_ON_ALWAYS_INCLUDED,
ALWAYS_INCLUDED,
ANNOTATION,
ANNOTATION_VALUE,
BASE_LAYER,
BRING_DATASOURCE,
EXPECTED_FILE,
Expand All @@ -48,6 +50,7 @@ public enum RULE {
}
private final Map<String, Set<Layer>> constantPoolClassInfos = new HashMap<>();
private final Map<String, Set<Layer>> annotations = new HashMap<>();
private final Map<String, Map<String, List<AnnotationFieldValue>>> annotationFieldValues = new HashMap<>();
private final Map<String, Layer> activeProfilesLayers = new HashMap<>();
private final Map<String, Set<Layer>> allProfilesLayers = new HashMap<>();
private Layer defaultBaseLayer;
Expand Down Expand Up @@ -176,6 +179,10 @@ public Map<Layer, String> getHiddenConditions() {
return hiddenConditions;
}

public Map<String, Map<String, List<AnnotationFieldValue>>> getAnnotationFieldValues() {
return annotationFieldValues;
}

public static String cleanupKey(String key) {
if (key.startsWith(LayerMetadata.HIDDEN_IF)) {
key = key.substring(key.indexOf(LayerMetadata.HIDDEN_IF) + LayerMetadata.HIDDEN_IF.length() + 1, key.length());
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/wildfly/glow/LayerMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public abstract class LayerMetadata {
public static final String ADD_ON_DESCRIPTION = PREFIX + "add-on-description";
public static final String ADD_ON_FIX = PREFIX + "add-on-fix-";
public static final String ANNOTATIONS = PREFIX + "annotations";
public static final String ANNOTATION_FIELD_VALUE = PREFIX + "annotation.field.value";
public static final String BRING_DATASOURCE = PREFIX + "bring-datasource";
public static final String CLASS = PREFIX + "class";
public static final String CONFIGURATION = PREFIX + "configuration";
Expand Down Expand Up @@ -67,6 +68,7 @@ public abstract class LayerMetadata {
FULLY_NAMED_RULES.add(KIND);

RULES_WITH_SUFFIX.add(ADD_ON_FIX);
RULES_WITH_SUFFIX.add(ANNOTATION_FIELD_VALUE);
RULES_WITH_SUFFIX.add(EXPECTED_FILE);
RULES_WITH_SUFFIX.add(NOT_EXPECTED_FILE);
RULES_WITH_SUFFIX.add(PROFILE);
Expand Down
17 changes: 17 additions & 0 deletions core/src/main/java/org/wildfly/glow/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -417,6 +418,22 @@ public static LayerMapping buildMapping(Map<String, Layer> layers, Set<String> p
}
continue;
}
if (k.startsWith(LayerMetadata.ANNOTATION_FIELD_VALUE)) {
String val = l.getProperties().get(k);
int i = val.indexOf(",");
String annotation = val.substring(0, i);
String annotationFieldValue = val.substring(i+1);
int j = annotationFieldValue.indexOf("=");
String field = annotationFieldValue.substring(0,j);
String fieldValue = annotationFieldValue.substring(j+1);
if (Utils.isPattern(fieldValue)) {
fieldValue = Utils.escapePattern(fieldValue);
}
Map<String, List<AnnotationFieldValue>> ll = mapping.getAnnotationFieldValues().computeIfAbsent(annotation, value -> new HashMap<>());
List<AnnotationFieldValue> lst = ll.computeIfAbsent(field, value -> new ArrayList<>());
lst.add(new AnnotationFieldValue(annotation, field, fieldValue, l));
continue;
}
if (LayerMetadata.CLASS.equals(k)) {
String val = l.getProperties().get(k);
String[] split = val.split(",");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import org.wildfly.glow.DataSourceDefinitionInfo;
import org.wildfly.glow.Env;

import static org.wildfly.glow.Utils.getAddOnFix;
Expand All @@ -51,9 +52,11 @@ public class DatasourceErrorIdentification implements ErrorIdentification {

private static final String UNBOUND_DATASOURCES_ERROR = "unbound-datasources";
private static final String NO_DEFAULT_DATASOURCE_ERROR = "no-default-datasource";
private static final String UNKNOWN_DRIVER_ERROR = "unknown-driver";
private static final String UNBOUND_DATASOURCES_ERROR_DESCRIPTION = "unbound datasources error";
private static final String NO_DEFAULT_DATASOURCE_ERROR_DESCRIPTION = "no default datasource found error";
Map<String, Set<IdentifiedError>> errors = new HashMap<>();
private Map<String, DataSourceDefinitionInfo> datasourceDefinitionInfos;

@Override
public void collectErrors(Path rootPath) throws Exception {
Expand Down Expand Up @@ -130,32 +133,42 @@ public Map<Layer, Set<Env>> refreshErrors(Set<Layer> allBaseLayers) throws Excep
if (unboundDatasourcesErrors != null) {
for (IdentifiedError error : unboundDatasourcesErrors) {
UnboundDatasourceError uds = (UnboundDatasourceError) error;
for (Layer l : allBaseLayers) {
if (l.getBringDatasources().contains(uds.unboundDatasource)) {
// The error is directly handled, we can remove it.
toRemove.add(uds.unboundDatasource);
break;
} else {
if (l.getAddOn() != null) {
Fix fix = l.getAddOn().getFixes().get(error.getId());
if (fix != null) {
String content = null;
if (!l.getBringDatasources().contains(uds.unboundDatasource)) {
content = fix.getContent();
if (content != null) {
content = content.replaceAll("##ITEM##", uds.unboundDatasource);
}
if (fix.isEnv()) {
Set<Env> envs = ret.get(l);
if (envs == null) {
envs = new HashSet<>();
ret.put(l, envs);
if (datasourceDefinitionInfos.containsKey(uds.unboundDatasource)) {
toRemove.add(uds.unboundDatasource);
DataSourceDefinitionInfo di = datasourceDefinitionInfos.get(uds.unboundDatasource);
if (di.getDriverLayer() == null) {
Set<IdentifiedError> errs = errors.computeIfAbsent(UNKNOWN_DRIVER_ERROR, res -> new HashSet<>());
errs.add(new IdentifiedError("Unknown driver", "The driver located in the URL [" + di.getUrl() + "] for the datasource " + uds.unboundDatasource
+ " injected thanks to the jakarta.annotation.sql.DataSourceDefinition annotation is not known.", ErrorLevel.WARN));
}
} else {
for (Layer l : allBaseLayers) {
if (l.getBringDatasources().contains(uds.unboundDatasource)) {
// The error is directly handled, we can remove it.
toRemove.add(uds.unboundDatasource);
break;
} else {
if (l.getAddOn() != null) {
Fix fix = l.getAddOn().getFixes().get(error.getId());
if (fix != null) {
String content = null;
if (!l.getBringDatasources().contains(uds.unboundDatasource)) {
content = fix.getContent();
if (content != null) {
content = content.replaceAll("##ITEM##", uds.unboundDatasource);
}
if (fix.isEnv()) {
Set<Env> envs = ret.get(l);
if (envs == null) {
envs = new HashSet<>();
ret.put(l, envs);
}
envs.add(new Env(fix.getEnvName(), Fix.getEnvValue(content), false, true, false));
}
envs.add(new Env(fix.getEnvName(), Fix.getEnvValue(content), false, true, false));
}
String errorMessage = getAddOnFix(l.getAddOn(), content);
error.setFixed(errorMessage);
}
String errorMessage = getAddOnFix(l.getAddOn(), content);
error.setFixed(errorMessage);
}
}
}
Expand Down Expand Up @@ -203,4 +216,8 @@ public List<IdentifiedError> getErrors() {
}
return ret;
}

void setDataSourceDefinitionInfos(Map<String, DataSourceDefinitionInfo> datasourceDefinitionInfos) {
this.datasourceDefinitionInfos = datasourceDefinitionInfos;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.wildfly.glow.DataSourceDefinitionInfo;
import org.wildfly.glow.Env;

/**
Expand All @@ -52,8 +53,10 @@ public void collectEndOfScanErrors(
boolean verbose,
Map<String, ResourceInjectionJndiInfo> resourceInjectionInfos,
Set<ContextLookupInfo> initialContextLookupInfos,
Map<String, DataSourceDefinitionInfo> datasourceDefinitionInfos,
Set<String> allClasses) {
jndiErrorIdentification.collectErrors(verbose, resourceInjectionInfos, initialContextLookupInfos, allClasses);
ds.setDataSourceDefinitionInfos(datasourceDefinitionInfos);
}

public Map<Layer, Set<Env>> refreshErrors(Set<Layer> allBaseLayers, LayerMapping mapping, Set<AddOn> enabledAddOns) throws Exception {
Expand Down
Loading