PT 152801833 - Added support for negative matches parsing for live
conditionals
This commit is contained in:
@@ -16,7 +16,7 @@ public class LiveConditional {
|
||||
private String message;
|
||||
private String processId;
|
||||
private String processName;
|
||||
private String positiveMatchKey;
|
||||
private String typeInfo;
|
||||
|
||||
public LiveConditional() {
|
||||
|
||||
@@ -38,8 +38,8 @@ public class LiveConditional {
|
||||
return processName;
|
||||
}
|
||||
|
||||
public String getPositiveMatchKey() {
|
||||
return positiveMatchKey;
|
||||
public String getTypeInfo() {
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
public static class LiveConditionalBuilder {
|
||||
@@ -67,13 +67,31 @@ public class LiveConditional {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a JSON key in "positiveMatches" element in the autoconfig report that contains information regarding
|
||||
* the method that the conditional is applied to.
|
||||
* @param positiveMatchKey
|
||||
* Type information for which a conditional is applied to.
|
||||
* <p/>
|
||||
*
|
||||
* Example:
|
||||
* <p/>
|
||||
* For this class:
|
||||
* <p/>
|
||||
* "@ConditionalOnClass(name="java.lang.String2")
|
||||
* public class MyConditionalComponent {
|
||||
* }"
|
||||
* <p/>
|
||||
* This is the "real" autoconfig JSON:
|
||||
* <p/>
|
||||
* "negativeMatches": { "MyConditionalComponent": { "notMatched": [ {
|
||||
* "condition": "OnClassCondition", "message": "@ConditionalOnClass did not find
|
||||
* required class 'java.lang.String2'" } ], "matched": [] }
|
||||
* <p/>
|
||||
* In this example, "MyConditionalComponent" information in the JSON indicates the type where the conditional is being applied to.
|
||||
* <p/>
|
||||
* Type info can also contain method information if a conditional annotation is applied to a method. Example: MyConditionalComponent#myBean)
|
||||
* @param typeInfo
|
||||
* @return
|
||||
*/
|
||||
public LiveConditionalBuilder positiveMatchKey(String positiveMatchKey) {
|
||||
conditional.positiveMatchKey = positiveMatchKey;
|
||||
public LiveConditionalBuilder typeInfo(String typeInfo) {
|
||||
conditional.typeInfo = typeInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ public class LiveConditionalParser {
|
||||
if (StringUtil.hasText(autoConfigRecord)) {
|
||||
getConditionalsFromPositiveMatches(autoConfigRecord).stream()
|
||||
.forEach(conditional -> allConditionals.add(conditional));
|
||||
getConditionalsFromNegativeMatches(autoConfigRecord).stream()
|
||||
.forEach(conditional -> allConditionals.add(conditional));
|
||||
}
|
||||
if (!allConditionals.isEmpty()) {
|
||||
return Optional.of(allConditionals);
|
||||
@@ -61,9 +63,7 @@ public class LiveConditionalParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the "positiveMatches" element in the autoconfig report that contains conditional information.
|
||||
* @param positiveMatchKey
|
||||
* @return
|
||||
* Fetches the "positiveMatches" element in the autoconfig report JSON that contains conditional information.
|
||||
*/
|
||||
private Optional<JSONObject> getPositiveMatchesJson(String autoConfigReport) {
|
||||
JSONObject autoConfigJson = new JSONObject(autoConfigReport);
|
||||
@@ -83,46 +83,100 @@ public class LiveConditionalParser {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the "negativeMatches" element in the autoconfig report JSON that contains conditional information.
|
||||
*/
|
||||
private Optional<JSONObject> getNegativeMatchesJson(String autoConfigReport) {
|
||||
JSONObject autoConfigJson = new JSONObject(autoConfigReport);
|
||||
|
||||
Iterator<String> keys = autoConfigJson.keys();
|
||||
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
if ("negativeMatches".equals(key)) {
|
||||
Object obj = autoConfigJson.get(key);
|
||||
if (obj instanceof JSONObject) {
|
||||
return Optional.of((JSONObject) obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all the conditionals listed in the the "positiveMatches" element in the autoconfig report.
|
||||
*
|
||||
*/
|
||||
private List<LiveConditional> getConditionalsFromPositiveMatches(String autoconfigReport) {
|
||||
private List<LiveConditional> getConditionalsFromPositiveMatches(String autoConfigReport) {
|
||||
List<LiveConditional> conditions = new ArrayList<>();
|
||||
|
||||
getPositiveMatchesJson(autoconfigReport).ifPresent((positiveMatches) -> {
|
||||
Iterator<String> pMKeys = positiveMatches.keys();
|
||||
while (pMKeys.hasNext()) {
|
||||
getPositiveMatchesJson(autoConfigReport).ifPresent((matches) -> {
|
||||
matches.keySet().stream().forEach(typeInfo -> {
|
||||
// The positive match key contains the bean method information where conditional
|
||||
// was applied to
|
||||
String positiveMatchKey = pMKeys.next();
|
||||
JSONArray matchList = (JSONArray) positiveMatches.get(positiveMatchKey);
|
||||
matchList.forEach((match) -> {
|
||||
if (match instanceof JSONObject) {
|
||||
resolveConditional(positiveMatchKey, (JSONObject) match)
|
||||
.ifPresent((condition) -> conditions.add(condition));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
Object val = matches.get(typeInfo);
|
||||
if (val instanceof JSONArray) {
|
||||
JSONArray contentList = (JSONArray) val;
|
||||
parseConditionalsFromContentList(conditions, typeInfo, contentList);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
return conditions;
|
||||
}
|
||||
|
||||
private Optional<LiveConditional> resolveConditional(String positiveMatchKey, JSONObject conditionalJson) {
|
||||
if (conditionalJson != null) {
|
||||
String condition = (String) conditionalJson.get("condition");
|
||||
String message = (String) conditionalJson.get("message");
|
||||
// We care about the message itself as it contains the actual annotation as well
|
||||
// as the reason it matched
|
||||
if (StringUtil.hasText(message)) {
|
||||
return Optional.of(LiveConditional.builder().processId(appProcessId).processName(appProcessName)
|
||||
.condition(condition).message(message).positiveMatchKey(positiveMatchKey).build());
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
private List<LiveConditional> getConditionalsFromNegativeMatches(String autoConfigReport) {
|
||||
List<LiveConditional> conditions = new ArrayList<>();
|
||||
// The JSON structure being parsed is:
|
||||
// "negativeMatches": {
|
||||
// "MyConditionalComponent": {
|
||||
// "notMatched": [
|
||||
// {
|
||||
// "condition": "OnClassCondition",
|
||||
// "message": "@ConditionalOnClass did not find required class 'java.lang.String2'"
|
||||
// }
|
||||
// ],
|
||||
// "matched": []
|
||||
// }
|
||||
getNegativeMatchesJson(autoConfigReport).ifPresent((matches) -> {
|
||||
// The key in the "matches" JSON contains the live type information where the conditional was applied to
|
||||
matches.keySet().stream().forEach(typeInfo -> {
|
||||
// The positive match key contains the bean method information where conditional
|
||||
// was applied to
|
||||
Object val = matches.get(typeInfo);
|
||||
if (val instanceof JSONObject) {
|
||||
JSONObject negativeMatches = (JSONObject) val;
|
||||
negativeMatches.keySet().stream().forEach((key) -> {
|
||||
JSONArray contentList = (JSONArray) negativeMatches.get(key);
|
||||
parseConditionalsFromContentList(conditions, typeInfo, contentList);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
return conditions;
|
||||
}
|
||||
|
||||
private void parseConditionalsFromContentList(List<LiveConditional> conditionals, String typeInfo,
|
||||
JSONArray contentList) {
|
||||
contentList.forEach((content) -> {
|
||||
if (content instanceof JSONObject) {
|
||||
JSONObject conditionalJson = (JSONObject) content;
|
||||
String condition = (String) conditionalJson.get("condition");
|
||||
String message = (String) conditionalJson.get("message");
|
||||
// We care about the message itself as it contains the actual annotation as well
|
||||
// as the reason it matched
|
||||
if (StringUtil.hasText(message)) {
|
||||
LiveConditional conditional = LiveConditional.builder().processId(appProcessId)
|
||||
.processName(appProcessName).condition(condition).message(message).typeInfo(typeInfo)
|
||||
.build();
|
||||
conditionals.add(conditional);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static Optional<List<LiveConditional>> parse(String autoConfigRecord, String appProcessId,
|
||||
String appProcessName) {
|
||||
return new LiveConditionalParser(autoConfigRecord, appProcessId, appProcessName).parse();
|
||||
|
||||
@@ -251,7 +251,7 @@ public class SpringBootApp {
|
||||
*/
|
||||
public static Optional<List<LiveConditional>> getLiveConditionals(String autoConfigReport, String processId,
|
||||
String processName) {
|
||||
return new LiveConditionalParser(autoConfigReport, processId, processName).parse();
|
||||
return LiveConditionalParser.parse(autoConfigReport, processId, processName);
|
||||
}
|
||||
|
||||
public String getAutoConfigReport() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user