From bec1ea3b5d55219866a41554b15d95449115d013 Mon Sep 17 00:00:00 2001 From: PavithraSuresh Date: Wed, 20 Aug 2025 18:31:05 +0530 Subject: [PATCH 1/6] Java 17 changes --- .circleci/config.yml | 8 ++-- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- ulyp-agent-api/build.gradle | 26 +++++------ ulyp-agent-core/build.gradle | 35 ++++++++------- ulyp-agent-tests/build.gradle | 6 ++- .../java/com/agent/tests/util/TestUtil.java | 26 +++++++++++ ulyp-agent/build.gradle | 44 ++++++++++++------- ulyp-benchmarks/build.gradle | 5 ++- ulyp-common/build.gradle | 16 +++---- ulyp-storage/build.gradle | 5 +-- ulyp-ui/build-jdk11.gradle | 20 --------- ulyp-ui/build.gradle | 19 +++++--- 13 files changed, 120 insertions(+), 94 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index dda261c6..504e7935 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,17 +5,17 @@ jobs: environment: GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2" docker: - - image: circleci/openjdk:8u312-buster-node-browsers + - image: cimg/openjdk:8.0.442 steps: - checkout - run: name: "Run gradle build" command: "chmod +x gradlew && ./gradlew ulyp-common:check ulyp-storage:check ulyp-agent-core:check ulyp-agent-tests:check -i" - jdk-14-build: + jdk-17-build: environment: GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2" docker: - - image: circleci/openjdk:14.0.2-buster-node-browsers-legacy + - image: cimg/openjdk:17.0.14 steps: - checkout - run: @@ -26,4 +26,4 @@ workflows: build-workflow: jobs: - jdk-8-build - - jdk-14-build + - jdk-17-build diff --git a/gradle.properties b/gradle.properties index 468f7e96..7221a91c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ major_version=1.0 -minor_version=1 +minor_version=2 mod= \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d8937ab4..1be2a039 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip diff --git a/ulyp-agent-api/build.gradle b/ulyp-agent-api/build.gradle index c7d60982..af189b13 100644 --- a/ulyp-agent-api/build.gradle +++ b/ulyp-agent-api/build.gradle @@ -1,23 +1,23 @@ plugins { id 'java' - id 'io.freefair.lombok' version '5.3.0' - id 'com.google.protobuf' version '0.8.8' - id "com.github.johnrengelman.shadow" version "2.0.4" + id 'io.freefair.lombok' version '8.12.1' + id 'com.google.protobuf' version '0.8.19' + id "com.gradleup.shadow" version "8.3.6" } -def protocVersion = '3.11.0' +def protocVersion = '3.21.12' dependencies { - compileOnly project(':ulyp-common') - compileOnly project(':ulyp-storage') + implementation project(':ulyp-common') + implementation project(':ulyp-storage') - compileOnly group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' - compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' - compileOnly group: 'io.grpc', name: 'grpc-netty', version: '1.27.0' - compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' + implementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' + implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' + implementation group: 'io.grpc', name: 'grpc-netty', version: '1.57.2' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' - implementation group: 'io.grpc', name: 'grpc-protobuf', version: '1.27.0' - implementation group: 'io.grpc', name: 'grpc-stub', version: '1.27.0' + implementation group: 'io.grpc', name: 'grpc-protobuf', version: '1.57.2' + implementation group: 'io.grpc', name: 'grpc-stub', version: '1.57.2' implementation group: 'com.google.protobuf', name: 'protobuf-java-util', version: '3.11.0' testImplementation group: 'io.grpc', name: 'grpc-testing', version: '1.55.1' @@ -26,7 +26,7 @@ dependencies { protobuf { protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" } plugins { - grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.27.0" } + grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.57.2" } } generateProtoTasks { all()*.plugins { grpc {} } diff --git a/ulyp-agent-core/build.gradle b/ulyp-agent-core/build.gradle index 81cf2ae5..d708e590 100644 --- a/ulyp-agent-core/build.gradle +++ b/ulyp-agent-core/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java' - id 'io.freefair.lombok' version '5.3.0' - id "com.github.johnrengelman.shadow" version "2.0.4" + id 'io.freefair.lombok' version '8.12.1' + id "com.gradleup.shadow" version "8.3.6" } test { @@ -14,15 +14,19 @@ dependencies { implementation group: 'com.lmax', name: 'disruptor', version: '3.4.4' implementation group: 'org.agrona', name: 'agrona', version: '1.4.0' - implementation group: 'org.jetbrains', name: 'annotations', version: '18.0.0' - implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' - compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24' - annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24' - compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' + shadow group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' + shadow group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' + shadow group: 'org.jetbrains', name: 'annotations', version: '18.0.0' + shadow group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' + shadow group: 'net.bytebuddy', name: 'byte-buddy', version: '1.17.6' - testImplementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' - testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.14.13' + shadow group: 'org.projectlombok', name: 'lombok', version: '1.18.28' + annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.28' + shadow group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' + + testImplementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' + testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.17.6' testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' @@ -49,22 +53,19 @@ compileJava { options.debug = true } -jar { - from { - configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } - } -} - shadowJar { + dependsOn 'jar' + relocate 'org.agrona', 'shadowed.org.agrona' + relocate 'org.intellij', 'shadowed.org.intellij' + relocate 'org.jetbrains', 'shadowed.org.jetbrains' relocate 'org.slf4j', 'com.ulyp.slf4j' relocate 'io', 'shadowed.io' relocate 'com.google', 'shadowed.com.google' relocate 'javax.annotation', 'shadowed.javax.annotation' - relocate 'net.bytebuddy', 'shadowed.net.bytebuddy' relocate 'com.lmax', 'shadowed.com.lmax' - archiveName = "${rootProject.name}-agent-core-${rootProject.version}.jar" + archiveFileName = "${rootProject.name}-agent-core-${rootProject.version}.jar" mergeServiceFiles() diff --git a/ulyp-agent-tests/build.gradle b/ulyp-agent-tests/build.gradle index 37380277..e904185e 100644 --- a/ulyp-agent-tests/build.gradle +++ b/ulyp-agent-tests/build.gradle @@ -31,7 +31,7 @@ dependencies { testImplementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' testImplementation group: 'org.rocksdb', name: 'rocksdbjni', version: '9.7.3' testImplementation group: 'org.buildobjects', name: 'jproc', version: '2.8.2' - testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.15.10' + testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.17.6' testImplementation group: 'org.buildobjects', name: 'jproc', version: '2.8.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' @@ -55,6 +55,10 @@ sourceSets { main.java.srcDirs = ['src/main/java', '../src/main/java'] } +compileKotlin { + dependsOn(':ulyp-agent-core:copyShadowJar') +} + test { dependsOn(':ulyp-agent:shadowJar') } \ No newline at end of file diff --git a/ulyp-agent-tests/src/test/java/com/agent/tests/util/TestUtil.java b/ulyp-agent-tests/src/test/java/com/agent/tests/util/TestUtil.java index 2d289901..81174ef2 100644 --- a/ulyp-agent-tests/src/test/java/com/agent/tests/util/TestUtil.java +++ b/ulyp-agent-tests/src/test/java/com/agent/tests/util/TestUtil.java @@ -3,6 +3,7 @@ import org.buildobjects.process.ProcBuilder; import org.buildobjects.process.ProcResult; import org.junit.jupiter.api.Assertions; +import org.opentest4j.AssertionFailedError; import java.io.File; import java.nio.file.Path; @@ -12,9 +13,14 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class TestUtil { + private static final Pattern JDK_VERSION_PATTERN = Pattern.compile("(\\d\\d)\\..*"); + private static final int OPEN_MODULES_JDK_VERSION = 17; + public static void runClassInSeparateJavaProcess(ForkProcessBuilder settingsBuilder) { File agentJar = findAgentJar(); String classPath = System.getProperty("java.class.path"); @@ -27,6 +33,7 @@ public static void runClassInSeparateJavaProcess(ForkProcessBuilder settingsBuil processArgs.add("-javaagent:" + agentJar.getAbsolutePath()); processArgs.add("-cp"); processArgs.add(classPath); + openJavaModules(processArgs); processArgs.addAll(settingsBuilder.toCmdJavaProps()); processArgs.add(settingsBuilder.getMainClass().getName()); @@ -47,6 +54,25 @@ public static void runClassInSeparateJavaProcess(ForkProcessBuilder settingsBuil } } + private static void openJavaModules(List processArgs) { + String jdkVersionRaw = System.getProperty("java.version"); + Matcher matcher = JDK_VERSION_PATTERN.matcher(jdkVersionRaw); + if (matcher.matches()) { + int jdkVersion; + try { + jdkVersion = Integer.parseInt(matcher.group(1)); + } catch (NumberFormatException numberFormatException) { + throw new AssertionFailedError("Could not define java version from " + jdkVersionRaw); + } + + if (jdkVersion >= OPEN_MODULES_JDK_VERSION) { + processArgs.add("--add-opens=java.base/java.lang=ALL-UNNAMED"); + processArgs.add("--add-opens=java.base/java.lang.invoke=ALL-UNNAMED"); + processArgs.add("--add-opens=java.base/sun.nio.ch=ALL-UNNAMED"); + } + } + } + private static File findAgentJar() { Path libDir = Paths.get("..", "ulyp-agent", "build", "libs"); diff --git a/ulyp-agent/build.gradle b/ulyp-agent/build.gradle index 3ea86125..e8d5cfb6 100644 --- a/ulyp-agent/build.gradle +++ b/ulyp-agent/build.gradle @@ -1,21 +1,28 @@ plugins { id 'java' - id 'io.freefair.lombok' version '5.3.0' - id "com.github.johnrengelman.shadow" version "2.0.4" + id 'io.freefair.lombok' version '8.12.1' + id "com.gradleup.shadow" version "8.3.6" } dependencies { implementation project(':ulyp-common') - compileOnly project(':ulyp-agent-core') + implementation project(':ulyp-agent-core') + + /* + We are embedding ulyp-agent-core jar file inside ulyp-agent jar file. ulyp-agent-core jar is copied to temp folder + and attached to bootstrap class loader on agent startup. + */ + shadow project(':ulyp-agent-core') runtimeOnly files('../ulyp-agent-core/build/libs/ulyp-agent-core.jarr') - compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' - compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' - compileOnly group: 'org.jetbrains', name: 'annotations', version: '18.0.0' - compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24' - annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24' - testImplementation project(':ulyp-agent-core') + shadow group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' + shadow group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' + shadow group: 'org.jetbrains', name: 'annotations', version: '18.0.0' + shadow group: 'org.projectlombok', name: 'lombok', version: '1.18.28' + annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.28' + testImplementation project(':ulyp-common') + testImplementation project(':ulyp-agent-core') testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2' @@ -27,7 +34,7 @@ if (project.hasProperty("customByteBuddy")) { } } else { dependencies { - implementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.15.10' + implementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.17.6' } } @@ -60,16 +67,19 @@ classes { compileJava { options.debug = true + dependsOn(':ulyp-agent-core:shadowJar') + dependsOn(':ulyp-agent-core:copyShadowJar') } -jar { - from { - configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } +shadowJar { + + archiveClassifier.set('all') + manifest { + attributes 'Premain-Class': 'com.ulyp.agent.UlypAgent', + 'Can-Redefine-Classes': 'true', + 'Can-Retransform-Classes': 'true' } -} -shadowJar { - dependsOn(':ulyp-agent-core:shadowJar') dependsOn(':ulyp-agent-core:copyShadowJar') relocate 'org.agrona', 'shadowed.org.agrona' @@ -79,7 +89,7 @@ shadowJar { relocate 'javax.annotation', 'shadowed.javax.annotation' relocate 'net.bytebuddy', 'shadowed.net.bytebuddy' - archiveName = "${rootProject.name}-agent-${rootProject.version}.jar" + archiveFileName = "${rootProject.name}-agent-${rootProject.version}.jar" mergeServiceFiles() diff --git a/ulyp-benchmarks/build.gradle b/ulyp-benchmarks/build.gradle index e5da613a..80202fc1 100644 --- a/ulyp-benchmarks/build.gradle +++ b/ulyp-benchmarks/build.gradle @@ -27,7 +27,6 @@ dependencies { jmhImplementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' jmhImplementation group: 'org.jetbrains', name: 'annotations', version: '18.0.0' jmhImplementation group: 'org.rocksdb', name: 'rocksdbjni', version: '9.7.3' - jmhImplementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' jmhImplementation group: 'com.hazelcast', name: 'hazelcast', version: '5.5.0' jmhImplementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.2' @@ -45,6 +44,10 @@ compileJava { options.debug = true } +compileJmhJava { + dependsOn(':ulyp-agent-core:copyShadowJar', ':ulyp-agent-core:shadowJar') +} + def jmhArgs = [] if (project.hasProperty('jmhProf')) { jmhArgs.add('-prof') diff --git a/ulyp-common/build.gradle b/ulyp-common/build.gradle index c5a3f768..6ac62638 100644 --- a/ulyp-common/build.gradle +++ b/ulyp-common/build.gradle @@ -15,20 +15,18 @@ test { useJUnitPlatform() } -sourceCompatibility = 1.8 - dependencies { - compileOnly group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' - compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' - compileOnly group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' - compileOnly group: 'org.agrona', name: 'agrona', version: '1.4.0' - compileOnly group: 'org.jetbrains', name: 'annotations', version: '18.0.0' - compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' + implementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' + implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2' + implementation group: 'org.agrona', name: 'agrona', version: '1.4.0' + implementation group: 'org.jetbrains', name: 'annotations', version: '18.0.0' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' + implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' - testImplementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' testImplementation group: 'org.agrona', name: 'agrona', version: '1.4.0' testImplementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.3' } \ No newline at end of file diff --git a/ulyp-storage/build.gradle b/ulyp-storage/build.gradle index 0e1d2405..0658a554 100644 --- a/ulyp-storage/build.gradle +++ b/ulyp-storage/build.gradle @@ -15,21 +15,18 @@ test { useJUnitPlatform() } -sourceCompatibility = 1.8 - dependencies { implementation project(':ulyp-common') compileOnly group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' - compileOnly group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' implementation group: 'org.agrona', name: 'agrona', version: '1.4.0' implementation group: 'org.jetbrains', name: 'annotations', version: '18.0.0' implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.2' + implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' compileOnly group: 'org.rocksdb', name: 'rocksdbjni', version: '9.7.3' testImplementation group: 'org.rocksdb', name: 'rocksdbjni', version: '9.7.3' - testImplementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' implementation group: 'org.jetbrains', name: 'annotations', version: '18.0.0' testImplementation group: 'org.awaitility', name: 'awaitility', version: '4.1.1' diff --git a/ulyp-ui/build-jdk11.gradle b/ulyp-ui/build-jdk11.gradle index 0f84412e..2f41b38f 100644 --- a/ulyp-ui/build-jdk11.gradle +++ b/ulyp-ui/build-jdk11.gradle @@ -1,34 +1,14 @@ -apply plugin: "org.openjfx.javafxplugin" def javaVersion = JavaVersion.current() println "Java version: $javaVersion, JDK 11+ compatible artifacts will be built" -def openjfxVersion = "17.0.1" - -def javafxModules = [ - 'javafx.controls', - 'javafx.fxml', - 'javafx.swing' -] String jarPlatform = project.findProperty("platform") -javafx { - version = openjfxVersion - modules = javafxModules -} if (jarPlatform != null) { javafx { platform = jarPlatform } } -dependencies { - javafxModules.each { - def javafxModuleArtifact = it.replace(".", "-") - if (jarPlatform != null) { - runtimeOnly "org.openjfx:$javafxModuleArtifact:$javafx.version:$jarPlatform" - } - } -} diff --git a/ulyp-ui/build.gradle b/ulyp-ui/build.gradle index baf53795..328d8d15 100644 --- a/ulyp-ui/build.gradle +++ b/ulyp-ui/build.gradle @@ -12,8 +12,13 @@ plugins { id 'org.jetbrains.kotlin.jvm' version '1.6.21' id 'org.jetbrains.kotlin.plugin.lombok' version '1.6.21' id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.21' - id 'io.freefair.lombok' version '5.3.0' - id 'org.openjfx.javafxplugin' version '0.0.14' apply(false) + id 'io.freefair.lombok' version '8.12.1' + id 'org.openjfx.javafxplugin' version '0.1.0' +} + +javafx { + version = "21.0.3" + modules = ['javafx.controls', 'javafx.fxml', 'javafx.swing'] } def javaVersion = JavaVersion.current() @@ -42,12 +47,13 @@ dependencies { implementation group: 'org.springframework', name: 'spring-context', version: '5.2.8.RELEASE' implementation group: 'org.springframework', name: 'spring-core', version: '5.2.8.RELEASE' - implementation group: 'org.rocksdb', name: 'rocksdbjni', version: '9.7.3' - implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' + implementation group: 'org.rocksdb', name: 'rocksdbjni', version: '10.2.1' implementation group: 'org.agrona', name: 'agrona', version: '1.4.0' + implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.12' + runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.2' - compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24' - annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24' + compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.28' + annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.28' implementation group: 'com.fifesoft', name: 'rsyntaxtextarea', version: '3.4.0' implementation group: 'com.github.javaparser', name: 'javaparser-core', version: '3.16.1' @@ -58,6 +64,7 @@ dependencies { testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + } mainClassName = 'com.ulyp.ui.UIStarter' From 2407d8bc1a1a5f72ec0e4674cca857a5443ef179 Mon Sep 17 00:00:00 2001 From: PavithraSuresh Date: Tue, 26 Aug 2025 11:13:51 +0530 Subject: [PATCH 2/6] Convert dat to json file --- .../RecordedEnterMethodCallSerializer.java | 1 + ulyp-ui/build.gradle | 2 ++ .../main/kotlin/com/ulyp/ui/PrimaryView.kt | 29 +++++++++++++++++-- .../com/ulyp/ui/reader/ReaderRegistry.kt | 5 ++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/ulyp-common/src/main/java/com/ulyp/core/serializers/RecordedEnterMethodCallSerializer.java b/ulyp-common/src/main/java/com/ulyp/core/serializers/RecordedEnterMethodCallSerializer.java index a449e9f4..59a918d7 100644 --- a/ulyp-common/src/main/java/com/ulyp/core/serializers/RecordedEnterMethodCallSerializer.java +++ b/ulyp-common/src/main/java/com/ulyp/core/serializers/RecordedEnterMethodCallSerializer.java @@ -103,6 +103,7 @@ public static RecordedEnterMethodCall deserialize(BytesIn input, ReadableReposit ObjectRecord callee = deserializeObject(input, typeResolver); + //System.out.println("Deserialized Object Record" + callee.getType().getName()); return RecordedEnterMethodCall.builder() .methodId(methodId) .nanoTime(nanoTime) diff --git a/ulyp-ui/build.gradle b/ulyp-ui/build.gradle index 328d8d15..a55a6acc 100644 --- a/ulyp-ui/build.gradle +++ b/ulyp-ui/build.gradle @@ -61,6 +61,8 @@ dependencies { implementation group: 'org.apache.logging.log4j', name: 'log4j', version: '2.24.2' implementation group: 'org.jetbrains', name: 'annotations', version: '18.0.0' + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.19.2' + testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt index 8175fbab..e1e78dbc 100644 --- a/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt @@ -11,6 +11,7 @@ import com.ulyp.ui.elements.controls.ErrorModalView import com.ulyp.ui.elements.misc.ExceptionAsTextView import com.ulyp.ui.elements.recording.tree.FileRecordingTabPane import com.ulyp.ui.elements.recording.tree.FileRecordingsTabName +import com.ulyp.ui.export.RecordingJsonExporter import com.ulyp.ui.reader.ReaderRegistry import com.ulyp.ui.settings.Settings import com.ulyp.ui.util.FxThreadExecutor @@ -133,12 +134,19 @@ class PrimaryView( } fun openRecordingFile() { - val file: File = fileChooser.get() ?: return + val file: File = fileChooser.get() ?: return // Retrieves the file selected by the user + + // `readerRegistry` processes the file and creates a `CallRecordTree` object containing metadata and recording data val callRecordTree: CallRecordTree = readerRegistry.newCallRecordTree(file) ?: return + // Creates or retrieves a tab for the file val fileRecordingsTab = fileRecordingTabPane.getOrCreateProcessTab( FileRecordingsTabName(file, callRecordTree.processMetadata) ) + + /* Cleanup action is registered + * When the tab is closed, the `CallRecordTree` is disposed of, and its resources are released + */ fileRecordingsTab.setOnClosed { readerRegistry.dispose(callRecordTree) callRecordTree.close() @@ -159,12 +167,28 @@ class PrimaryView( loadingProgressBar.prefWidth = 200.0 fileTabPaneAnchorPane.children.add(loadingProgressBar) + /* Subscribe to `CallRecordTree` object Updates: + * `RecordingListener` is registered to handle updates from the `CallRecordTree`. It listens for: + * Recording Updates: Updates the tab with new recording data + * Progress Updates: Updates the progress bar every 5% increment + */ callRecordTree.subscribe( object : RecordingListener { var prevProgress = 0.0 override fun onRecordingUpdated(recording: Recording) { fileRecordingsTab.updateOrCreateRecordingTab(callRecordTree.processMetadata, recording) + + // NEW: export JSON next to the opened .dat file (or choose another directory) +// val outDir = file.parentFile ?: File(".") +// val outFile = File(outDir, "recording-${recording.id}.json") // Creates a JSON file for each recording +// RecordingJsonExporter.export(recording, outFile) + + callRecordTree.completeFuture.thenRun { + val baseDir = file.parentFile ?: File(".") + val combined = File(baseDir, "all-recordings.json") + RecordingJsonExporter.exportAll(callRecordTree, combined) + } } override fun onProgressUpdated(progress: Double) { @@ -179,9 +203,10 @@ class PrimaryView( } ) + // Handle Completion or Errors callRecordTree.completeFuture.exceptionally { FxThreadExecutor.execute { - loadingProgressBar.visibleProperty().set(false) + loadingProgressBar.visibleProperty().set(false) // Progress bar is removed from the UI fileTabPaneAnchorPane.children.remove(loadingProgressBar) val errorPopup = applicationContext.getBean( ErrorModalView::class.java, diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/reader/ReaderRegistry.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/reader/ReaderRegistry.kt index 76b33c57..1d575d6b 100644 --- a/ulyp-ui/src/main/kotlin/com/ulyp/ui/reader/ReaderRegistry.kt +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/reader/ReaderRegistry.kt @@ -16,6 +16,11 @@ class ReaderRegistry(private val filterRegistry: FilterRegistry) { private val readersMap = ConcurrentHashMap() + /* ReaderRegistry constructs: + * a low‑level file reader (RecordingDataReader) from the file + * an index (RocksDB if available, otherwise in‑memory), + * and a CallRecordTree that will parse the stream of bytes from the file, build a call tree, and publish incremental updates (progress + parsed “recordings”). + */ @Synchronized fun newCallRecordTree(file: File): CallRecordTree? { val recordingDataReader = FileRecordingDataReaderBuilder(file).build() From 2ed984bbe1b21ad4c608efc766fd1c5d9ce14192 Mon Sep 17 00:00:00 2001 From: PavithraSuresh Date: Thu, 28 Aug 2025 14:32:41 +0530 Subject: [PATCH 3/6] Exporting dat to JSON file --- .../main/kotlin/com/ulyp/ui/PrimaryView.kt | 23 +-- .../com/ulyp/ui/export/AllRecordingsJson.kt | 11 ++ .../com/ulyp/ui/export/RecordingJson.kt | 29 ++++ .../ulyp/ui/export/RecordingJsonConverter.kt | 141 ++++++++++++++++++ .../export/RecordingMultipleJsonExporter.kt | 25 ++++ 5 files changed, 218 insertions(+), 11 deletions(-) create mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/ui/export/AllRecordingsJson.kt create mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJson.kt create mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt create mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingMultipleJsonExporter.kt diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt index e1e78dbc..4151fed0 100644 --- a/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/PrimaryView.kt @@ -11,7 +11,7 @@ import com.ulyp.ui.elements.controls.ErrorModalView import com.ulyp.ui.elements.misc.ExceptionAsTextView import com.ulyp.ui.elements.recording.tree.FileRecordingTabPane import com.ulyp.ui.elements.recording.tree.FileRecordingsTabName -import com.ulyp.ui.export.RecordingJsonExporter +import com.ulyp.ui.export.RecordingMultipleJsonExporter import com.ulyp.ui.reader.ReaderRegistry import com.ulyp.ui.settings.Settings import com.ulyp.ui.util.FxThreadExecutor @@ -179,16 +179,17 @@ class PrimaryView( override fun onRecordingUpdated(recording: Recording) { fileRecordingsTab.updateOrCreateRecordingTab(callRecordTree.processMetadata, recording) - // NEW: export JSON next to the opened .dat file (or choose another directory) -// val outDir = file.parentFile ?: File(".") -// val outFile = File(outDir, "recording-${recording.id}.json") // Creates a JSON file for each recording -// RecordingJsonExporter.export(recording, outFile) - - callRecordTree.completeFuture.thenRun { - val baseDir = file.parentFile ?: File(".") - val combined = File(baseDir, "all-recordings.json") - RecordingJsonExporter.exportAll(callRecordTree, combined) - } + // Export JSON next to the opened .dat file (or choose another directory) + val outDir = file.parentFile ?: File(".") + val outFile = File(outDir, "recording-${recording.id}.json") // Creates a JSON file for each recording + RecordingMultipleJsonExporter.export(recording, outFile) + + // Export ALL recordings to a single file +// callRecordTree.completeFuture.thenRun { +// val baseDir = file.parentFile ?: File(".") +// val combined = File(baseDir, "all-recordings.json") +// RecordingJsonConverter.exportAll(callRecordTree, combined) +// } } override fun onProgressUpdated(progress: Double) { diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/AllRecordingsJson.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/AllRecordingsJson.kt new file mode 100644 index 00000000..3d224e8c --- /dev/null +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/AllRecordingsJson.kt @@ -0,0 +1,11 @@ +package com.ulyp.ui.export + +/** + * The "all recordings in one file" JSON. + * - count: how many recordings we exported + * - recordings: left-pane summary + right-pane tree per recording + */ +data class AllRecordingsJson( + val count: Int, + val recordings: List +) diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJson.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJson.kt new file mode 100644 index 00000000..a9bd6491 --- /dev/null +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJson.kt @@ -0,0 +1,29 @@ +package com.ulyp.ui.export + +/** + * Top-level JSON model for one Recording. + * Mirrors the left pane summary + the right pane call tree. + */ +data class RecordingJson( + val id: Int, + val threadName: String?, + val startTimeEpochMs: Long?, + val durationMillis: Long, + val totalCalls: Int, + val root: NodeJson // the right-pane call tree (single root per recording) +) + +/** + * One node in the call tree (right pane). + * Built by walking CallRecord -> children recursively. + */ +data class NodeJson( + val nodeId: Long?, // callRecord.getId() (nullable in case of future changes) + val ownerClass: String?, // callRecord.getMethod().getType().getName() + val methodName: String?, // callRecord.getMethod().getName() + val args: List, // callRecord.getArgs() stringified + val returnValue: String?, // callRecord.getReturnValue() stringified + val thrown: Boolean, // callRecord.hasThrown() + val durationNanos: Long, // callRecord.getNanosDuration() + val children: List // recursively filled with child call records +) diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt new file mode 100644 index 00000000..bbab2526 --- /dev/null +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt @@ -0,0 +1,141 @@ +package com.ulyp.ui.export + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.SerializationFeature +import com.ulyp.core.recorders.ObjectRecord +import com.ulyp.storage.tree.CallRecord +import com.ulyp.storage.tree.CallRecordTree +import com.ulyp.storage.tree.Recording +import java.io.File + +/** + * Exports a parsed Recording (Java object) to JSON shaped like your UI. + * + * LEFT PANE: + * - id, threadName, startTimeEpochMs, durationMillis, totalCalls (all from Recording/RecordingMetadata) + * + * RIGHT PANE: + * - root call (CallRecord) recursively expanded to children: + * ownerClass.methodName(args) -> returnValue / thrown / durationNanos + * + */ +object RecordingJsonConverter { + + // Single ObjectMapper instance; pretty printing enabled for readability in files. + private val mapper = ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT) + + /** + * Export ALL currently published recordings in a CallRecordTree to ONE JSON file. + * + * Safe to call multiple times while parsing progresses: it just overwrites the file + * with the latest list from tree.getRecordings(). + */ + fun exportAll(tree: CallRecordTree, outFile: File) { + // Pull all *published* recordings. CallRecordTree already filters via RecordingState.isPublished(). + val recordings: List = tree.recordings + + // Convert each to the same JSON shape you already use for single-file exports. + val list: List = recordings.map(::toRecordingJson) + + // Wrap into a single payload + val payload = AllRecordingsJson( + count = list.size, + recordings = list + ) + + outFile.parentFile?.mkdirs() + mapper.writeValue(outFile, payload) + println("Exported ${list.size} recordings to ${outFile.absolutePath}") + } + + // -------------- Internal: per-recording conversion (left summary + right tree) -------------- + + /** Builds RecordingJson (left-pane summary + right-pane tree) from a Recording. */ + fun toRecordingJson(recording: Recording): RecordingJson { + // LEFT PANE: all precomputed in your model + // Thread name / start time come from RecordingMetadata + val md = recording.metadata + // Recording identity + val id: Int = recording.id + val threadName: String? = md.threadName + val startEpochMs: Long? = md.recordingStartedMillis + // Root call duration (Duration) -> millis (matches UI "ms") + val durationMs: Long = recording.rootDuration().toMillis() + // Total number of calls in this recording (matches UI count) + val totalCalls: Int = recording.callCount() + + + // RIGHT PANE: walk the CallRecord tree starting from the root + + // Your Recording always has exactly one root call + val rootCall: CallRecord = recording.root + // Recursively convert the root CallRecord to a DTO tree + val rootDto: NodeJson = toNodeJson(rootCall) + + // -------- Build the top-level DTO -------- + val recording = RecordingJson( + id = id, + threadName = threadName, + startTimeEpochMs = startEpochMs, + durationMillis = durationMs, + totalCalls = totalCalls, + root = rootDto + ) + + println("Converted recording $id with $totalCalls calls to JSON DTO") + return recording + } + + + /** + * RECURSION: + * Converts a CallRecord (one node) into NodeJson, then does the same for each child. + */ + private fun toNodeJson(node: CallRecord): NodeJson { + // Stable node id within the recording session (starts at 0 per your docs) + val nodeId: Long? = node.id + + // Method owner (class) and method name come from node.getMethod() + val ownerClass: String? = node.method.type.name + val methodName: String? = node.method.name + + // Arguments and return value are ObjectRecord; stringifying is enough for the JSON + val args: List = node.args.map(::renderObjectRecord) + val returnValue: String? = renderObjectRecordOrNull(node.returnValue) + + // Whether the method threw during this call + val thrown: Boolean = node.hasThrown() + + // Duration of this call in nanoseconds (per-node timing available in CallRecord) + val durationNanos: Long = node.nanosDuration + + // Children: CallRecord resolves children lazily via RecordingState using child ids + val children: List = node.getChildren().map { child -> toNodeJson(child) } + + return NodeJson( + nodeId = nodeId, + ownerClass = ownerClass, + methodName = methodName, + args = args, + returnValue = returnValue, + thrown = thrown, + durationNanos = durationNanos, + children = children + ) + } + + // ---------- Small helpers to render ObjectRecord safely ---------- + + private fun renderObjectRecord(obj: ObjectRecord): String { + // ObjectRecord implementations have sensible toString() for UI display. + // Using toString() keeps JSON aligned with what the right pane shows. + return obj.toString() + } + + private fun renderObjectRecordOrNull(obj: ObjectRecord?): String? { + // Some return values may be "not recorded"; toString() still works, + // but we'll keep it nullable in case an implementation returns null. + return obj?.toString() + } + +} diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingMultipleJsonExporter.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingMultipleJsonExporter.kt new file mode 100644 index 00000000..bcee76c7 --- /dev/null +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingMultipleJsonExporter.kt @@ -0,0 +1,25 @@ +package com.ulyp.ui.export + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.SerializationFeature +import com.ulyp.storage.tree.Recording +import java.io.File + +object RecordingMultipleJsonExporter { + + // Single ObjectMapper instance; pretty printing enabled for readability in files. + private val mapper = ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT) + + /** + * Export one Recording to a JSON file on disk. + * + * @param recording Parsed Recording object (NOT raw bytes) + * @param outFile Destination JSON file path + */ + fun export(recording: Recording, outFile: File) { + val dto = RecordingJsonConverter.toRecordingJson(recording) + outFile.parentFile?.mkdirs() + mapper.writeValue(outFile, dto) + } + +} From 2db1be921979229c533c5b2f1978c9ba4f03eb84 Mon Sep 17 00:00:00 2001 From: Pavithra Suresh Date: Wed, 28 Jan 2026 13:28:02 +0530 Subject: [PATCH 4/6] Converting dat to JSON file --- .DS_Store | Bin 0 -> 14340 bytes all.log | 0 ulyp-storage/src/.DS_Store | Bin 0 -> 6148 bytes ulyp-storage/src/main/.DS_Store | Bin 0 -> 6148 bytes ulyp-storage/src/main/java/.DS_Store | Bin 0 -> 6148 bytes ulyp-storage/src/main/java/com/.DS_Store | Bin 0 -> 6148 bytes ulyp-storage/src/main/java/com/ulyp/.DS_Store | Bin 0 -> 6148 bytes .../src/main/java/com/ulyp/storage/.DS_Store | Bin 0 -> 6148 bytes ulyp-ui/src/.DS_Store | Bin 0 -> 6148 bytes ulyp-ui/src/main/.DS_Store | Bin 0 -> 6148 bytes ulyp-ui/src/main/kotlin/.DS_Store | Bin 0 -> 6148 bytes ulyp-ui/src/main/kotlin/com/.DS_Store | Bin 0 -> 6148 bytes ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store | Bin 0 -> 6148 bytes ulyp-ui/src/main/kotlin/com/ulyp/ui/.DS_Store | Bin 0 -> 6148 bytes .../main/kotlin/com/ulyp/ui/PrimaryView.kt | 109 ++++++++++++++++-- .../ulyp/ui/export/RecordingJsonConverter.kt | 4 +- ulyp-ui/src/main/resources/.DS_Store | Bin 0 -> 6148 bytes ulyp-ui/src/main/resources/PrimaryView.fxml | 1 + 18 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 .DS_Store create mode 100644 all.log create mode 100644 ulyp-storage/src/.DS_Store create mode 100644 ulyp-storage/src/main/.DS_Store create mode 100644 ulyp-storage/src/main/java/.DS_Store create mode 100644 ulyp-storage/src/main/java/com/.DS_Store create mode 100644 ulyp-storage/src/main/java/com/ulyp/.DS_Store create mode 100644 ulyp-storage/src/main/java/com/ulyp/storage/.DS_Store create mode 100644 ulyp-ui/src/.DS_Store create mode 100644 ulyp-ui/src/main/.DS_Store create mode 100644 ulyp-ui/src/main/kotlin/.DS_Store create mode 100644 ulyp-ui/src/main/kotlin/com/.DS_Store create mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store create mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/ui/.DS_Store create mode 100644 ulyp-ui/src/main/resources/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4851ddf99bbfb56c5fe85c8a963f508b91c2ab24 GIT binary patch literal 14340 zcmeHNO>7%Q6n>L5v7MyENz*_JsFosxgo^95R4s~t)Jdp9|Drfe6WZeVXX9?W-gS4^ zaYIxo2ZV&^0SRvO0JjQ>3aLUWsEBevAOr|#sl);G*aH$O>IKB1yqR5lXVzYCfC6pU zwRUGb`@Na>Gw=D$cmRMT%lSco1OSBbre(AXA1?#MXvtmlJ-zF$R%{`7=kUgQ6krib z@Hk|k08$;gzM%!1DE%6|?}IWZ0=)_*>#GFvLP}Q^O)W6Ij^imS>L2036=)#PK%jv@ z1Aztt4Y)Kwe|zx?cUooe3^WjEAkaWf12jIw@TTRkT`pTC3my2NDLj2oQ+Re^9oGS@ zEoPU)cDZboj1*}YDV7!~v6mRcBFFX^g=0Bvm&;aZkpr>Ff!HGxdxb*S=tvi1a3I50 z89W0G1RAK|)*dP-iPf$)^4wTT*1h zOeC(6mew_G?V)fu+!;QaI;K@pX2vWV$&7xOew)%XC0ng$veU9uNk{ueG}X+=s-!al zIWHmP$RSzHYn7x{R`Uj?AQWpt?#wx8Lat;Dd!e!G0C@8F|S8^s)9y3I=j~1*B$NY zUDwyUzPG=>umAoB`ZsLc_)t2!E}O}nDCks#5lzwbq*9h< z!c9u~7o4W4#S&uroCem{Ze5bp!v$T=ADEvvBy)zV&pw|yHC5}q+sNsfqD*LpY|5HC zd&EFPjGIz%T%Ff&@C7u&ff9XXOiQ|fWjgAjnVHS#dPXfs$;G2eCMzii)TCybT9G1Y zZz$7*F43MC8>vzzC#!{lXKq@W9vGgkR^nDA3IkRJv(&z7%`VB5s;N>WGBCWyZVBUl z(Fp8?gK!*ol3s(ea1JiOr|=!zfZs?f=^+DT3)x9_k>|)>a*#}u0#Qhjs1|)o)%*{O zBasSz_c6ax7)<4~Vu?|Ahh3g{ds`ZIKb8+9e98~KjqawI;CWYKw4+{``(Mcgvi;Y6JqU2(aQ54E7f)`?k{ zn>QGb*I@aJpU!<;AA}lGIr>{Um7u*ai(y4Tk=*SZ_M+VIny?#XWvE5G3QF~fLfX+$@jgevbBQM~a&vvbsVu6|r5 zqln-NH1NOCzz|9rfjFiiGX5-C|Ey!3cT@axf1)vpch%*uPwIyrV{4cO{qa$^Ig)o- zw&6fG7vp%MKn7Fb>h;Jaye_;^0zVLQ_@T)|o}PdZ`02PnSFzSeH3ZL(F~x;as!tB( zXvP~Q@Y6L%`DsJ_$jFNX8G#pAnit>ld`zo@S8u(+<_Sm7>!dM47@sWD@k6Ky1wV1T zH7JO`uXGIxL);p)4YFuO8L@d664Puiq$n316s4~9!^?Fg(^0nPoPcn2+ZZ9p#RkCq zqBa7Xfi+8seAC2O;Jcl-stb$Br8icT^7~DQ75d`keEXZ)ymnz6Nxd+ltT(B&Jv`4S zZ3*Y4hEEAg6Rm~&3!)@6ZxSR42|ZLqG@AuqakHRPMB|8AoJFRKip~h0svS9@i!^$! z$;A(|f+tqcZ2X;**sstRui2Ta^0nPo#BgC8&3a)3&Bia|Fz6k7VI23v#$Z3BU`&*d z(D}e~9f3(i?t)R&*cfW1==Kt(cb=jfcYY+a5w((vnlYNqRkkCP=IpSx0rhcgt6Tm7 zT?F%#9b8szSp-jtxul~@Mqiqy8TLK2Gu==j!G_xE-cW03bRpU#&zk7t4RL(bc_e&ZhHGt)^Z$1n+W|j;1_BM- zK@E^Kqp8s(c33?C;qIHBwTt0Bhd0Gs#+zPPXC(Mw$MLXa$MNtBJ&w1Nf$Rsq8>Uq( lm#q?Oc>U`K0lA$os08c(+qan+g7yDBdor!zvdwo@@CQ+bvLyfj literal 0 HcmV?d00001 diff --git a/all.log b/all.log new file mode 100644 index 00000000..e69de29b diff --git a/ulyp-storage/src/.DS_Store b/ulyp-storage/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..15f3dbcc6a7cc6704c49a1d607e990b52a63788c GIT binary patch literal 6148 zcmeHKPjAyO6o2jlb2lLsX-Mp5i5sd!Q#4Iz5(=f;2OwxWY*R@{wM8Ux)ui-LRmvT{ z2;#z(FRZ@@BL|($m{}b zv`+^L7()(4Z9g#kT=iA=^XaOxACsHPpZmGZU)#@$9bCYQWxz6E8E7(K4hg>9bXkjK zz%uZkGeGBqKqd4HmKxR3fsHBw5FIot!9LXzlp_p!21||TL18)-QKvFfVlbVKc46W? zgQZ5D4$KrE%&g2zg~HV8IKNQgz&wq%wG3DW>I`h?VTbPj!(Z3`^&~s83|I#KDF&D` z^oIj{By+bm9**u>f%*oOgyKq#>lEy$s~BVHDt?Hn1nq)4h@QbxBU(`GkAR}VHkN@u G%D@kK@PQ=& literal 0 HcmV?d00001 diff --git a/ulyp-storage/src/main/.DS_Store b/ulyp-storage/src/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..67e664d6fd97a191c6be9b37c6cb721cb7bf822e GIT binary patch literal 6148 zcmeHK%}N6?5Kd~<6cKt*&|AQp6zo<+M3A*sAHWqosMKAz=<0S;`eP5Juy=hJuU@@) z^XS2+aVAMiOVy(knSsfd%uka2c1d;^W4zo69mevEF#(F0$wBjtpdWQYGS)H&$Z?LK z+iC={3Sj&)5lx0^WB}h?mfbO*JurXt{RNFUYPE~S51yIH&d$w?d9ffay<64w+J3v! zD*MfI9Gxf?2ZO#JoJO^7HNSMAlC~cuwWdyp!Wx8JoJC2fx@FZ#!j{hUj6>u^u9{!% z^)`!J1z9TX^b4}*I3=ebx3;(Y{hU}{+t@v>-pBPsJsK7{d~jM8Ee_xbI>QHwZyfJh z)f?K$m)=Kxbyca@k5#-npL<8^Z~No^@K=B1c4Y3%GcGY)_rYr>u}W^hHrOZnNr(Yr zfEbt(2JF!!7N%rBv<+f_7?>Ug@O+S@UE4hSD+{uml_l&T2E_iNE)*hB{K-8pQ`Qg+Sq<@XomX;O@u%_m-|I&ZdWq9(S*MR=tq z;ixwn7eR0M4M%56rO~|Ki_Vk&q+8!PQrW1NWc{H|Na8+(eE*tcv6=*GoW+IC4UI#% z!tK`grqd72c0;yWA7>3Y^}LqXknO|6*~}I1_TPUx?fyy!nYuA7a`@o1ytO!oTj(qv zD82N;pK6e6C*OHo_6=00V?S0Aw4Xnp96Wqk^~bOJ^Q)z~D|fiWV%^{2FiTZ-3AXt@ z(N97Q5Cg=(hA?1{Cb7LC`=MkL4SavU|eZ%kpdlk6+8j7m%iVlR@t9sNzxr>U5tk>VfuD@_Hiut8M^yKjww*bm9Aq-JsSG^$nHbg@7D40>D1xOk!FiJR>k;r#9T)}*IJQ*U&A@C zx$wFC?{}9!Iyn9X_cFiF`(=1%U>?!f=RLU5yw>OPe&0L1g@3`j%kG` zbovSa3^1$>&wQ8QoXBEqF*gVgOqo=mNmcfWp-ei)BO4c6%nh1!Qkog_SY~B!C`z+q zJksH$VuR9)0-}Jgz@~Yv^Z9?W`u^`H$(tx33j8YtRFJfjCYEH+*2?1etc}n*Xlxvp m8`LT2>~X9g_$b~-(*|F}55U-BZV)3d`6HlZkWLg>s{(U21*HxE literal 0 HcmV?d00001 diff --git a/ulyp-ui/src/.DS_Store b/ulyp-ui/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c21e8b135d6ca4ede22cd2d6aa348725c5168dfb GIT binary patch literal 6148 zcmeHKPixyS6qk~$ktu^5Hdt?h!VV+QxY_7oFg(}o2bjlpSW9Nlp)qr;5GTta1blBl zK)*^qLFuihp88?-o}`3?v^|zk-h-!~^!`Zl&qnfNjB$UQxQsOzV*(Vh;z09&pdWQj zD%P?E$Z?K%QVilu#W22FizdS+GJx-{#`-K`Da)7NUp&atV$^Eg@k+J!YO5~lVq2Vs zJv9kO(P&)w(eM|JzAKf*^L`ZnNV}6x2vSjGFx`!B~IuD`DOlPCRy-qPIlTU=tX?!R!DXDUAf z+kBtsCm{xi0b*c77_di^*xr!+&^CwxVqkL^!1F_yvs-~1kdQ$P#q;|!=*3Z*H5wCES}HGBR`?2E z<6r!1IrOu3Hb|T8{yBY}N*M=JyB&OvI>T0N{YWNRJ4!lz6%d6Tbh$W-l28tta*%|n ziuLsXukvcEwmBN@?(WsaPNOldi;?5(ICb%Ee}6o#@;7g{-+yY|#N9;x&@3{%bdmCtbvWx2{?n&-{b-$vpydjAeDnKB zER!qjr`)U1hYqAj{s65@vJ06q@B4hO$N9eIa`I8PGe8~Fmo`u}m9WHETu^BMO zhp#R6Htp^#1D1hjFhKW%KqYhy<{H)2fsHBw5X;!D1Z}D%C`K4`4dxng1cm8PL>wVqf%+Adg#2=iDg+zz94mvK;tfFVQNx_Z}TnIYWs(VLtp;9|e(ZT7Y^kEmJFnj$Wzra6m z1O!ktWZCYKj^F)J?pTh;fw^=_|IskhIu zccN4rjN0|!G-~u~#rb`ebn8*lXzPF|Y=FzfS(JpTUs1gz?C4nE7(_u7YQ?3&V10d~ zB-hI2VMz{Lcg-!y&8@BBupkzeSGSLAcX2aO4~9by$4$$e#SuJ0!)_eV8#N~(Y&74!-%etc+<<1ZI<%4y1H=F^Fog`* zYf8*c;o4|P!~ikyw+!I@AfX_77E^=z>VQh80DxIgYk@ZA5*Q;bdKOcIU;*JK6wrin zn__Si4ti<*Jd3G86VA9zKDeEk+YE*4*if32!pi;YT(Z%g%>5oN9Vek4pf=}QZ zc=2VNNz&3%^(aMVVDcsNlVrbLk{!kvFLwfmu>xaEfFfq{(0n84N1c$2wd4Rf&f#}k zi61E+#%~kRWSB+<@ZDuuhehm(C8O`pPol8ZE|orbW+pqEn-gqU<@&hEtT=J3IY;UM#Jy@19m4qDHKq4T~H;I4uhn2k-)&;R8i?j(4jX ziFRh#{;02^Di!;&ir16Rz2mj_gK>ZGt3SCPnL8(OiQ&4BUNeqVd2hg>c S8Uzan{Rn6ps38Xalz}ff8fD4= literal 0 HcmV?d00001 diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store b/ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9f70cdae4a77bb8ba3eb47a5b316dd85669d6fa0 GIT binary patch literal 6148 zcmeHKJ5R$f5Vk{GTp^?mAi-t{u~nksp$-g$5=It+U;tDaQne9jT=hYRs#12?_%%$7 z`~!Xucecwzg%wrkPC9?~J?!{PYWEmpyf%zn#!8Ga0gC7pq4`13k2)icwG;q3&JiXm zg#L5bP2!noGRz|b`0gAwWN|p^cfY>B{-9EMMVv-zR8zw=>g(LVI7Cqt>!tPacxPv~ zEVnC_Nm-6vciSz?y=rwbDT>vNt^L#bUD8R_gJF=v$EIc3;uIdCqc@YZ+~8Jqy4vBe zgQ>lveBW+TJe|DcH~rVcPha$_uiO4IUqRxudY${AmnJH0!Fc*i=p!Kphyh|?&Ka;r zmROqe=cLCY28e;bX8_L!35w`h%na(I0~%cd0Or7~1^QS^V2-rtSU*z!a^l!E5s7lQzD!ggqC5(tH;yX9*v}8O@8$IO-?IIpO143S|_6qlg*$Q zo5vFK$Wt2(I=GIY)It9Qn_A3@G5I|0^fXHKWpWx8XY)#!mq%U6sqd}LKAJw0$L;m| z?v0v1yW3D0H<` zz$suWFsgnQc>iA?eEzqS+%KnqQ{Z1IAiS^=mhnh>Z%sWM@3lV4E(#mRB?@H() + + callRecordTree.subscribe( + object : RecordingListener { + var prevProgress = 0.0 + + override fun onRecordingUpdated(recording: Recording) { + recordingsById[recording.id] = recording + } + + override fun onProgressUpdated(progress: Double) { + // update every 5 percent at most + if (progress > prevProgress + 0.05) { + Platform.runLater { + loadingProgressBar.progress = progress + } + prevProgress = progress + } + } + } + ) + + callRecordTree.completeFuture.whenComplete { _, err -> + try { + if (err != null) { + FxThreadExecutor.execute { + val errorPopup = applicationContext.getBean( + ErrorModalView::class.java, + applicationContext.getBean(SceneRegistry::class.java), + "Stopped reading recording file $file with error: " + err.message, + ExceptionAsTextView(err) + ) + errorPopup.show() + } + return@whenComplete + } + + val outDir = file.parentFile ?: File(".") + recordingsById.values + .sortedBy { it.id } + .forEach { recording -> + val outFile = File(outDir, "recording-${recording.id}.json") + println("Exporting recording ${recording.id} to JSON file: ${outFile.absolutePath}") + RecordingMultipleJsonExporter.export(recording, outFile) + } + + } catch (e: Exception) { + FxThreadExecutor.execute { + val errorPopup = applicationContext.getBean( + ErrorModalView::class.java, + applicationContext.getBean(SceneRegistry::class.java), + "Failed to export $file to JSON: " + e.message, + ExceptionAsTextView(e) + ) + errorPopup.show() + } + } finally { + FxThreadExecutor.execute { + loadingProgressBar.visibleProperty().set(false) + fileTabPaneAnchorPane.children.remove(loadingProgressBar) + } + try { + readerRegistry.dispose(callRecordTree) + callRecordTree.close() + } catch (_: Exception) { + // best effort cleanup + } + } + } + } + } \ No newline at end of file diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt index bbab2526..44250f3e 100644 --- a/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt +++ b/ulyp-ui/src/main/kotlin/com/ulyp/ui/export/RecordingJsonConverter.kt @@ -73,7 +73,7 @@ object RecordingJsonConverter { val rootDto: NodeJson = toNodeJson(rootCall) // -------- Build the top-level DTO -------- - val recording = RecordingJson( + val recordingJson = RecordingJson( id = id, threadName = threadName, startTimeEpochMs = startEpochMs, @@ -83,7 +83,7 @@ object RecordingJsonConverter { ) println("Converted recording $id with $totalCalls calls to JSON DTO") - return recording + return recordingJson } diff --git a/ulyp-ui/src/main/resources/.DS_Store b/ulyp-ui/src/main/resources/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ea7b794527f294b7f3d732f6c8fffa6a36352627 GIT binary patch literal 6148 zcmeHKOHRW;47E!^L2R;QIcs(mdo)ym3-kh2TSSo>Qi-w;r-B=>VbKF{7@o&gXc8)R z2!Snm-o&4Y^HRk%5%KtOF(S%|D1!N^hTqA6 zyt_lXqd8S{Po4Mo^49j2RZ+}V)eP1we}2EXK6}0FMl8OGSTA>fAzP%=5p8HmH&jA9 z6`VhH{kt`6woMJKGs^0-ihVKdI;K*Gi!_pL5XTTY71{wzB`w*al z(XdubpAIZ(1ON_UPJ+G65|R@PqhYNG4}>)psHtot25UO(!Q!G}t*Gh5Hhi$%nQcPh zba$K|QaEu`^wk+~2HFf9=w&Yb|7!pI-%j!?XTTZwQw;F1m=t3?lJ(Z!!%43V&?!_z n;%dbv1)J205i70u6q*F~ARAybtQBE__#c5pgD=j&k23H9VMI#g literal 0 HcmV?d00001 diff --git a/ulyp-ui/src/main/resources/PrimaryView.fxml b/ulyp-ui/src/main/resources/PrimaryView.fxml index c321cb92..2560f647 100644 --- a/ulyp-ui/src/main/resources/PrimaryView.fxml +++ b/ulyp-ui/src/main/resources/PrimaryView.fxml @@ -15,6 +15,7 @@ + From 50c5d7a1c43f0e9713b4e676a9a8dd23d9c63175 Mon Sep 17 00:00:00 2001 From: Pavithra Suresh Date: Wed, 4 Feb 2026 22:24:19 +0530 Subject: [PATCH 5/6] Remove .DS_Store files to match upstream --- .DS_Store | Bin 14340 -> 0 bytes ulyp-storage/src/.DS_Store | Bin 6148 -> 0 bytes ulyp-storage/src/main/.DS_Store | Bin 6148 -> 0 bytes ulyp-storage/src/main/java/.DS_Store | Bin 6148 -> 0 bytes ulyp-storage/src/main/java/com/.DS_Store | Bin 6148 -> 0 bytes ulyp-storage/src/main/java/com/ulyp/.DS_Store | Bin 6148 -> 0 bytes .../src/main/java/com/ulyp/storage/.DS_Store | Bin 6148 -> 0 bytes ulyp-ui/src/.DS_Store | Bin 6148 -> 0 bytes ulyp-ui/src/main/.DS_Store | Bin 6148 -> 0 bytes ulyp-ui/src/main/kotlin/.DS_Store | Bin 6148 -> 0 bytes ulyp-ui/src/main/kotlin/com/.DS_Store | Bin 6148 -> 0 bytes ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store | Bin 6148 -> 0 bytes ulyp-ui/src/main/kotlin/com/ulyp/ui/.DS_Store | Bin 6148 -> 0 bytes ulyp-ui/src/main/resources/.DS_Store | Bin 6148 -> 0 bytes 14 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store delete mode 100644 ulyp-storage/src/.DS_Store delete mode 100644 ulyp-storage/src/main/.DS_Store delete mode 100644 ulyp-storage/src/main/java/.DS_Store delete mode 100644 ulyp-storage/src/main/java/com/.DS_Store delete mode 100644 ulyp-storage/src/main/java/com/ulyp/.DS_Store delete mode 100644 ulyp-storage/src/main/java/com/ulyp/storage/.DS_Store delete mode 100644 ulyp-ui/src/.DS_Store delete mode 100644 ulyp-ui/src/main/.DS_Store delete mode 100644 ulyp-ui/src/main/kotlin/.DS_Store delete mode 100644 ulyp-ui/src/main/kotlin/com/.DS_Store delete mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store delete mode 100644 ulyp-ui/src/main/kotlin/com/ulyp/ui/.DS_Store delete mode 100644 ulyp-ui/src/main/resources/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 4851ddf99bbfb56c5fe85c8a963f508b91c2ab24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14340 zcmeHNO>7%Q6n>L5v7MyENz*_JsFosxgo^95R4s~t)Jdp9|Drfe6WZeVXX9?W-gS4^ zaYIxo2ZV&^0SRvO0JjQ>3aLUWsEBevAOr|#sl);G*aH$O>IKB1yqR5lXVzYCfC6pU zwRUGb`@Na>Gw=D$cmRMT%lSco1OSBbre(AXA1?#MXvtmlJ-zF$R%{`7=kUgQ6krib z@Hk|k08$;gzM%!1DE%6|?}IWZ0=)_*>#GFvLP}Q^O)W6Ij^imS>L2036=)#PK%jv@ z1Aztt4Y)Kwe|zx?cUooe3^WjEAkaWf12jIw@TTRkT`pTC3my2NDLj2oQ+Re^9oGS@ zEoPU)cDZboj1*}YDV7!~v6mRcBFFX^g=0Bvm&;aZkpr>Ff!HGxdxb*S=tvi1a3I50 z89W0G1RAK|)*dP-iPf$)^4wTT*1h zOeC(6mew_G?V)fu+!;QaI;K@pX2vWV$&7xOew)%XC0ng$veU9uNk{ueG}X+=s-!al zIWHmP$RSzHYn7x{R`Uj?AQWpt?#wx8Lat;Dd!e!G0C@8F|S8^s)9y3I=j~1*B$NY zUDwyUzPG=>umAoB`ZsLc_)t2!E}O}nDCks#5lzwbq*9h< z!c9u~7o4W4#S&uroCem{Ze5bp!v$T=ADEvvBy)zV&pw|yHC5}q+sNsfqD*LpY|5HC zd&EFPjGIz%T%Ff&@C7u&ff9XXOiQ|fWjgAjnVHS#dPXfs$;G2eCMzii)TCybT9G1Y zZz$7*F43MC8>vzzC#!{lXKq@W9vGgkR^nDA3IkRJv(&z7%`VB5s;N>WGBCWyZVBUl z(Fp8?gK!*ol3s(ea1JiOr|=!zfZs?f=^+DT3)x9_k>|)>a*#}u0#Qhjs1|)o)%*{O zBasSz_c6ax7)<4~Vu?|Ahh3g{ds`ZIKb8+9e98~KjqawI;CWYKw4+{``(Mcgvi;Y6JqU2(aQ54E7f)`?k{ zn>QGb*I@aJpU!<;AA}lGIr>{Um7u*ai(y4Tk=*SZ_M+VIny?#XWvE5G3QF~fLfX+$@jgevbBQM~a&vvbsVu6|r5 zqln-NH1NOCzz|9rfjFiiGX5-C|Ey!3cT@axf1)vpch%*uPwIyrV{4cO{qa$^Ig)o- zw&6fG7vp%MKn7Fb>h;Jaye_;^0zVLQ_@T)|o}PdZ`02PnSFzSeH3ZL(F~x;as!tB( zXvP~Q@Y6L%`DsJ_$jFNX8G#pAnit>ld`zo@S8u(+<_Sm7>!dM47@sWD@k6Ky1wV1T zH7JO`uXGIxL);p)4YFuO8L@d664Puiq$n316s4~9!^?Fg(^0nPoPcn2+ZZ9p#RkCq zqBa7Xfi+8seAC2O;Jcl-stb$Br8icT^7~DQ75d`keEXZ)ymnz6Nxd+ltT(B&Jv`4S zZ3*Y4hEEAg6Rm~&3!)@6ZxSR42|ZLqG@AuqakHRPMB|8AoJFRKip~h0svS9@i!^$! z$;A(|f+tqcZ2X;**sstRui2Ta^0nPo#BgC8&3a)3&Bia|Fz6k7VI23v#$Z3BU`&*d z(D}e~9f3(i?t)R&*cfW1==Kt(cb=jfcYY+a5w((vnlYNqRkkCP=IpSx0rhcgt6Tm7 zT?F%#9b8szSp-jtxul~@Mqiqy8TLK2Gu==j!G_xE-cW03bRpU#&zk7t4RL(bc_e&ZhHGt)^Z$1n+W|j;1_BM- zK@E^Kqp8s(c33?C;qIHBwTt0Bhd0Gs#+zPPXC(Mw$MLXa$MNtBJ&w1Nf$Rsq8>Uq( lm#q?Oc>U`K0lA$os08c(+qan+g7yDBdor!zvdwo@@CQ+bvLyfj diff --git a/ulyp-storage/src/.DS_Store b/ulyp-storage/src/.DS_Store deleted file mode 100644 index 15f3dbcc6a7cc6704c49a1d607e990b52a63788c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKPjAyO6o2jlb2lLsX-Mp5i5sd!Q#4Iz5(=f;2OwxWY*R@{wM8Ux)ui-LRmvT{ z2;#z(FRZ@@BL|($m{}b zv`+^L7()(4Z9g#kT=iA=^XaOxACsHPpZmGZU)#@$9bCYQWxz6E8E7(K4hg>9bXkjK zz%uZkGeGBqKqd4HmKxR3fsHBw5FIot!9LXzlp_p!21||TL18)-QKvFfVlbVKc46W? zgQZ5D4$KrE%&g2zg~HV8IKNQgz&wq%wG3DW>I`h?VTbPj!(Z3`^&~s83|I#KDF&D` z^oIj{By+bm9**u>f%*oOgyKq#>lEy$s~BVHDt?Hn1nq)4h@QbxBU(`GkAR}VHkN@u G%D@kK@PQ=& diff --git a/ulyp-storage/src/main/.DS_Store b/ulyp-storage/src/main/.DS_Store deleted file mode 100644 index 67e664d6fd97a191c6be9b37c6cb721cb7bf822e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}N6?5Kd~<6cKt*&|AQp6zo<+M3A*sAHWqosMKAz=<0S;`eP5Juy=hJuU@@) z^XS2+aVAMiOVy(knSsfd%uka2c1d;^W4zo69mevEF#(F0$wBjtpdWQYGS)H&$Z?LK z+iC={3Sj&)5lx0^WB}h?mfbO*JurXt{RNFUYPE~S51yIH&d$w?d9ffay<64w+J3v! zD*MfI9Gxf?2ZO#JoJO^7HNSMAlC~cuwWdyp!Wx8JoJC2fx@FZ#!j{hUj6>u^u9{!% z^)`!J1z9TX^b4}*I3=ebx3;(Y{hU}{+t@v>-pBPsJsK7{d~jM8Ee_xbI>QHwZyfJh z)f?K$m)=Kxbyca@k5#-npL<8^Z~No^@K=B1c4Y3%GcGY)_rYr>u}W^hHrOZnNr(Yr zfEbt(2JF!!7N%rBv<+f_7?>Ug@O+S@UE4hSD+{uml_l&T2E_iNE)*hB{K-8pQ`Qg+Sq<@XomX;O@u%_m-|I&ZdWq9(S*MR=tq z;ixwn7eR0M4M%56rO~|Ki_Vk&q+8!PQrW1NWc{H|Na8+(eE*tcv6=*GoW+IC4UI#% z!tK`grqd72c0;yWA7>3Y^}LqXknO|6*~}I1_TPUx?fyy!nYuA7a`@o1ytO!oTj(qv zD82N;pK6e6C*OHo_6=00V?S0Aw4Xnp96Wqk^~bOJ^Q)z~D|fiWV%^{2FiTZ-3AXt@ z(N97Q5Cg=(hA?1{Cb7LC`=MkL4SavU|eZ%kpdlk6+8j7m%iVlR@t9sNzxr>U5tk>VfuD@_Hiut8M^yKjww*bm9Aq-JsSG^$nHbg@7D40>D1xOk!FiJR>k;r#9T)}*IJQ*U&A@C zx$wFC?{}9!Iyn9X_cFiF`(=1%U>?!f=RLU5yw>OPe&0L1g@3`j%kG` zbovSa3^1$>&wQ8QoXBEqF*gVgOqo=mNmcfWp-ei)BO4c6%nh1!Qkog_SY~B!C`z+q zJksH$VuR9)0-}Jgz@~Yv^Z9?W`u^`H$(tx33j8YtRFJfjCYEH+*2?1etc}n*Xlxvp m8`LT2>~X9g_$b~-(*|F}55U-BZV)3d`6HlZkWLg>s{(U21*HxE diff --git a/ulyp-ui/src/.DS_Store b/ulyp-ui/src/.DS_Store deleted file mode 100644 index c21e8b135d6ca4ede22cd2d6aa348725c5168dfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKPixyS6qk~$ktu^5Hdt?h!VV+QxY_7oFg(}o2bjlpSW9Nlp)qr;5GTta1blBl zK)*^qLFuihp88?-o}`3?v^|zk-h-!~^!`Zl&qnfNjB$UQxQsOzV*(Vh;z09&pdWQj zD%P?E$Z?K%QVilu#W22FizdS+GJx-{#`-K`Da)7NUp&atV$^Eg@k+J!YO5~lVq2Vs zJv9kO(P&)w(eM|JzAKf*^L`ZnNV}6x2vSjGFx`!B~IuD`DOlPCRy-qPIlTU=tX?!R!DXDUAf z+kBtsCm{xi0b*c77_di^*xr!+&^CwxVqkL^!1F_yvs-~1kdQ$P#q;|!=*3Z*H5wCES}HGBR`?2E z<6r!1IrOu3Hb|T8{yBY}N*M=JyB&OvI>T0N{YWNRJ4!lz6%d6Tbh$W-l28tta*%|n ziuLsXukvcEwmBN@?(WsaPNOldi;?5(ICb%Ee}6o#@;7g{-+yY|#N9;x&@3{%bdmCtbvWx2{?n&-{b-$vpydjAeDnKB zER!qjr`)U1hYqAj{s65@vJ06q@B4hO$N9eIa`I8PGe8~Fmo`u}m9WHETu^BMO zhp#R6Htp^#1D1hjFhKW%KqYhy<{H)2fsHBw5X;!D1Z}D%C`K4`4dxng1cm8PL>wVqf%+Adg#2=iDg+zz94mvK;tfFVQNx_Z}TnIYWs(VLtp;9|e(ZT7Y^kEmJFnj$Wzra6m z1O!ktWZCYKj^F)J?pTh;fw^=_|IskhIu zccN4rjN0|!G-~u~#rb`ebn8*lXzPF|Y=FzfS(JpTUs1gz?C4nE7(_u7YQ?3&V10d~ zB-hI2VMz{Lcg-!y&8@BBupkzeSGSLAcX2aO4~9by$4$$e#SuJ0!)_eV8#N~(Y&74!-%etc+<<1ZI<%4y1H=F^Fog`* zYf8*c;o4|P!~ikyw+!I@AfX_77E^=z>VQh80DxIgYk@ZA5*Q;bdKOcIU;*JK6wrin zn__Si4ti<*Jd3G86VA9zKDeEk+YE*4*if32!pi;YT(Z%g%>5oN9Vek4pf=}QZ zc=2VNNz&3%^(aMVVDcsNlVrbLk{!kvFLwfmu>xaEfFfq{(0n84N1c$2wd4Rf&f#}k zi61E+#%~kRWSB+<@ZDuuhehm(C8O`pPol8ZE|orbW+pqEn-gqU<@&hEtT=J3IY;UM#Jy@19m4qDHKq4T~H;I4uhn2k-)&;R8i?j(4jX ziFRh#{;02^Di!;&ir16Rz2mj_gK>ZGt3SCPnL8(OiQ&4BUNeqVd2hg>c S8Uzan{Rn6ps38Xalz}ff8fD4= diff --git a/ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store b/ulyp-ui/src/main/kotlin/com/ulyp/.DS_Store deleted file mode 100644 index 9f70cdae4a77bb8ba3eb47a5b316dd85669d6fa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5R$f5Vk{GTp^?mAi-t{u~nksp$-g$5=It+U;tDaQne9jT=hYRs#12?_%%$7 z`~!Xucecwzg%wrkPC9?~J?!{PYWEmpyf%zn#!8Ga0gC7pq4`13k2)icwG;q3&JiXm zg#L5bP2!noGRz|b`0gAwWN|p^cfY>B{-9EMMVv-zR8zw=>g(LVI7Cqt>!tPacxPv~ zEVnC_Nm-6vciSz?y=rwbDT>vNt^L#bUD8R_gJF=v$EIc3;uIdCqc@YZ+~8Jqy4vBe zgQ>lveBW+TJe|DcH~rVcPha$_uiO4IUqRxudY${AmnJH0!Fc*i=p!Kphyh|?&Ka;r zmROqe=cLCY28e;bX8_L!35w`h%na(I0~%cd0Or7~1^QS^V2-rtSU*z!a^l!E5s7lQzD!ggqC5(tH;yX9*v}8O@8$IO-?IIpO143S|_6qlg*$Q zo5vFK$Wt2(I=GIY)It9Qn_A3@G5I|0^fXHKWpWx8XY)#!mq%U6sqd}LKAJw0$L;m| z?v0v1yW3D0H<` zz$suWFsgnQc>iA?eEzqS+%KnqQ{Z1IAiS^=mhnh>Z%sWM@3lV4E(#mRB?@HQi-w;r-B=>VbKF{7@o&gXc8)R z2!Snm-o&4Y^HRk%5%KtOF(S%|D1!N^hTqA6 zyt_lXqd8S{Po4Mo^49j2RZ+}V)eP1we}2EXK6}0FMl8OGSTA>fAzP%=5p8HmH&jA9 z6`VhH{kt`6woMJKGs^0-ihVKdI;K*Gi!_pL5XTTY71{wzB`w*al z(XdubpAIZ(1ON_UPJ+G65|R@PqhYNG4}>)psHtot25UO(!Q!G}t*Gh5Hhi$%nQcPh zba$K|QaEu`^wk+~2HFf9=w&Yb|7!pI-%j!?XTTZwQw;F1m=t3?lJ(Z!!%43V&?!_z n;%dbv1)J205i70u6q*F~ARAybtQBE__#c5pgD=j&k23H9VMI#g From 56c12e85bf5408534a8a197f174235e36d75ee70 Mon Sep 17 00:00:00 2001 From: Pavithra Suresh Date: Wed, 4 Feb 2026 22:27:26 +0530 Subject: [PATCH 6/6] Revert changes as per master --- ulyp-ui/build-jdk11.gradle | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ulyp-ui/build-jdk11.gradle b/ulyp-ui/build-jdk11.gradle index 2f41b38f..0f84412e 100644 --- a/ulyp-ui/build-jdk11.gradle +++ b/ulyp-ui/build-jdk11.gradle @@ -1,14 +1,34 @@ +apply plugin: "org.openjfx.javafxplugin" def javaVersion = JavaVersion.current() println "Java version: $javaVersion, JDK 11+ compatible artifacts will be built" +def openjfxVersion = "17.0.1" + +def javafxModules = [ + 'javafx.controls', + 'javafx.fxml', + 'javafx.swing' +] String jarPlatform = project.findProperty("platform") +javafx { + version = openjfxVersion + modules = javafxModules +} if (jarPlatform != null) { javafx { platform = jarPlatform } } +dependencies { + javafxModules.each { + def javafxModuleArtifact = it.replace(".", "-") + if (jarPlatform != null) { + runtimeOnly "org.openjfx:$javafxModuleArtifact:$javafx.version:$jarPlatform" + } + } +}