-
Notifications
You must be signed in to change notification settings - Fork 27
Ctf2 fixes #365
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
base: master
Are you sure you want to change the base?
Ctf2 fixes #365
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,7 +35,9 @@ | |
| import java.nio.file.FileSystems; | ||
| import java.nio.file.Files; | ||
| import java.nio.file.Path; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.UUID; | ||
|
|
||
|
|
@@ -73,6 +75,9 @@ | |
|
|
||
| import com.google.gson.Gson; | ||
| import com.google.gson.GsonBuilder; | ||
| import com.google.gson.JsonElement; | ||
| import com.google.gson.JsonObject; | ||
| import com.google.gson.JsonParser; | ||
| import com.google.gson.JsonSyntaxException; | ||
|
|
||
| /** | ||
|
|
@@ -247,30 +252,42 @@ private static ICTFMetadataNode parseJsonToTree(String json) throws CTFException | |
| Gson gson = builder.create(); | ||
|
|
||
| String[] jsonBlocks = json.split("\u001e"); //$NON-NLS-1$ | ||
| Map<String, JsonObject> metadata = new HashMap<>(); | ||
|
|
||
| // Second pass: expand string references and parse | ||
| for (int i = 1; i < jsonBlocks.length; i++) { | ||
| JsonElement element = JsonParser.parseString(jsonBlocks[i]); | ||
| if (element.isJsonObject()) { | ||
| JsonObject obj = element.getAsJsonObject(); | ||
| expandAliases(obj, metadata); | ||
| if (obj.has(JsonMetadataStrings.TYPE) && obj.get(JsonMetadataStrings.TYPE).getAsString().equals(JsonMetadataStrings.FRAGMENT_FIELD_ALIAS)) { | ||
| metadata.put(obj.get(JsonMetadataStrings.NAME).getAsString(), obj.get(JsonMetadataStrings.FIELD_CLASS).getAsJsonObject()); | ||
| } | ||
|
Comment on lines
+263
to
+265
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null checks before accessing NAME and FIELD_CLASS. Line 264 assumes that FRAGMENT_FIELD_ALIAS nodes always have both NAME and FIELD_CLASS fields. If either is missing, this will throw a NullPointerException. Apply this diff to add defensive checks: if (obj.has(JsonMetadataStrings.TYPE) && obj.get(JsonMetadataStrings.TYPE).getAsString().equals(JsonMetadataStrings.FRAGMENT_FIELD_ALIAS)) {
- metadata.put(obj.get(JsonMetadataStrings.NAME).getAsString(), obj.get(JsonMetadataStrings.FIELD_CLASS).getAsJsonObject());
+ if (obj.has(JsonMetadataStrings.NAME) && obj.has(JsonMetadataStrings.FIELD_CLASS)) {
+ metadata.put(obj.get(JsonMetadataStrings.NAME).getAsString(), obj.get(JsonMetadataStrings.FIELD_CLASS).getAsJsonObject());
+ }
}🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| ICTFMetadataNode fragment; | ||
| try { | ||
| fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], CTFJsonMetadataNode.class)); | ||
| fragment = Objects.requireNonNull(gson.fromJson(element, CTFJsonMetadataNode.class)); | ||
| } catch (JsonSyntaxException e) { | ||
| throw new CTFException("Trace cannot be parsed as CTF2"); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| String type = fragment.getType(); | ||
| if (type.equals(JsonMetadataStrings.FRAGMENT_PREAMBLE)) { | ||
| fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonPreambleMetadataNode.class)); | ||
| fragment = Objects.requireNonNull(gson.fromJson(element, JsonPreambleMetadataNode.class)); | ||
| } else if (type.equals(JsonMetadataStrings.FRAGMENT_TRACE)) { | ||
| fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonTraceMetadataNode.class)); | ||
| fragment = Objects.requireNonNull(gson.fromJson(element, JsonTraceMetadataNode.class)); | ||
| } else if (type.equals(JsonMetadataStrings.FRAGMENT_CLOCK)) { | ||
| fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonClockMetadataNode.class)); | ||
| fragment = Objects.requireNonNull(gson.fromJson(element, JsonClockMetadataNode.class)); | ||
| } else if (type.equals(JsonMetadataStrings.FRAGMENT_EVENT_RECORD)) { | ||
| fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonEventRecordMetadataNode.class)); | ||
| fragment = Objects.requireNonNull(gson.fromJson(element, JsonEventRecordMetadataNode.class)); | ||
| } else if (type.equals(JsonMetadataStrings.FRAGMENT_DATA_STREAM)) { | ||
| fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonDataStreamMetadataNode.class)); | ||
| fragment = Objects.requireNonNull(gson.fromJson(element, JsonDataStreamMetadataNode.class)); | ||
| if (!jsonBlocks[i].contains("id:")) { //$NON-NLS-1$ | ||
| ((JsonDataStreamMetadataNode) fragment).setId(-1); | ||
| } | ||
| } else if (type.equals(JsonMetadataStrings.FRAGMENT_FIELD_ALIAS)) { | ||
| fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonFieldClassAliasMetadataNode.class)); | ||
| fragment = Objects.requireNonNull(gson.fromJson(element, JsonFieldClassAliasMetadataNode.class)); | ||
| } | ||
|
|
||
| ((CTFJsonMetadataNode) fragment).initialize(); | ||
|
|
@@ -281,6 +298,23 @@ private static ICTFMetadataNode parseJsonToTree(String json) throws CTFException | |
| return root; | ||
| } | ||
|
|
||
| private static void expandAliases(JsonObject obj, Map<String, JsonObject> metadata) { | ||
| for (String key : obj.keySet()) { | ||
| JsonElement value = obj.get(key); | ||
| if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isString() && metadata.containsKey(value.getAsString())) { | ||
| obj.add(key, metadata.get(value.getAsString())); | ||
| } else if (value.isJsonObject()) { | ||
| expandAliases(value.getAsJsonObject(), metadata); | ||
| } else if (value.isJsonArray()) { | ||
| for (JsonElement elem : value.getAsJsonArray()) { | ||
| if (elem.isJsonObject()) { | ||
| expandAliases(elem.getAsJsonObject(), metadata); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Checks the version of the CTF trace by reading the first JSON fragment if | ||
| * it is a CTF2 fragment it updates the major of the trace | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope; | ||
| import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration; | ||
| import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration; | ||
| import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration; | ||
| import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration; | ||
| import org.eclipse.tracecompass.ctf.core.trace.CTFTrace; | ||
| import org.eclipse.tracecompass.ctf.parser.CTFParser; | ||
|
|
@@ -266,7 +267,7 @@ public VariantDeclaration parse(ICTFMetadataNode variant, ICommonTreeParserParam | |
| if (variant instanceof JsonStructureFieldMemberMetadataNode) { | ||
| JsonObject fieldClass = ((JsonStructureFieldMemberMetadataNode) variant).getFieldClass().getAsJsonObject(); | ||
| if (fieldClass.has(SELECTOR_FIELD_LOCATION)) { | ||
| JsonArray location = fieldClass.get(SELECTOR_FIELD_LOCATION).getAsJsonArray(); | ||
| JsonArray location = (fieldClass.get(SELECTOR_FIELD_LOCATION).getAsJsonObject().get(JsonMetadataStrings.PATH)).getAsJsonArray(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null safety checks for nested JSON navigation. The chained method calls assume that Consider adding intermediate checks or using a try-catch block: if (fieldClass.has(SELECTOR_FIELD_LOCATION)) {
- JsonArray location = (fieldClass.get(SELECTOR_FIELD_LOCATION).getAsJsonObject().get(JsonMetadataStrings.PATH)).getAsJsonArray();
+ JsonElement selectorElement = fieldClass.get(SELECTOR_FIELD_LOCATION);
+ if (selectorElement != null && selectorElement.isJsonObject()) {
+ JsonElement pathElement = selectorElement.getAsJsonObject().get(JsonMetadataStrings.PATH);
+ if (pathElement != null && pathElement.isJsonArray()) {
+ JsonArray location = pathElement.getAsJsonArray();
- variantTag = location.get(location.size() - 1).getAsString();
- hasTag = true;
+ variantTag = location.get(location.size() - 1).getAsString();
+ hasTag = true;
+ }
+ }
}
🤖 Prompt for AI Agents |
||
| variantTag = location.get(location.size() - 1).getAsString(); | ||
| hasTag = true; | ||
| } | ||
|
|
@@ -361,13 +362,17 @@ public VariantDeclaration parse(ICTFMetadataNode variant, ICommonTreeParserParam | |
| if (decl == null) { | ||
| throw new ParseException("Variant tag not found: " + variantTag); //$NON-NLS-1$ | ||
| } | ||
| if (!(decl instanceof EnumDeclaration)) { | ||
| throw new ParseException("Variant tag must be an enum: " + variantTag); //$NON-NLS-1$ | ||
| } | ||
| EnumDeclaration tagDecl = (EnumDeclaration) decl; | ||
| if (!intersects(tagDecl.getLabels(), variantDeclaration.getFields().keySet())) { | ||
| throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$ | ||
| if (decl instanceof EnumDeclaration) { | ||
| EnumDeclaration tagDecl = (EnumDeclaration) decl; | ||
| if (!intersects(tagDecl.getLabels(), variantDeclaration.getFields().keySet())) { | ||
| throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$ | ||
| } | ||
| } else if (decl instanceof IntegerDeclaration) { | ||
| // do nothing | ||
| } else { | ||
| throw new ParseException("Variant tag must be an enum: " + variantTag);//$NON-NLS-1$ | ||
| } | ||
|
|
||
| } | ||
|
|
||
| return variantDeclaration; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify or correct the "Second pass" comment.
The comment states "Second pass" but there's no visible first pass in the code. The loop performs JSON parsing, alias expansion, and fragment creation in a single pass.
Consider updating the comment to accurately describe the operation:
📝 Committable suggestion
🤖 Prompt for AI Agents