adamsaghy commented on code in PR #6040:
URL: https://github.com/apache/fineract/pull/6040#discussion_r3480447667


##########
static-weaving.gradle:
##########
@@ -16,51 +16,174 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-// In static-weaving.gradle
+import org.gradle.api.artifacts.component.ProjectComponentIdentifier
 
-// Wait until after project evaluation to ensure all plugins are applied
+private static List<String> findJpaManagedClasses(Project moduleProject) {
+    File sourceRoot = moduleProject.file('src/main/java')
+    if (!sourceRoot.exists()) {
+        return []
+    }
+
+    moduleProject.fileTree(sourceRoot) {
+        include '**/*.java'
+    }.findAll { File javaSource ->
+        isJpaManagedClass(javaSource.text)
+    }.collect { File javaSource ->
+        toFullyQualifiedClassName(javaSource)
+    }.findAll {
+        it != null
+    }.unique().sort()
+}
+
+private static boolean isJpaManagedClass(String source) {
+    def hasManagedAnnotation = (source =~ 
/(?m)^\s*@((jakarta|javax)\.persistence\.)?(Entity|MappedSuperclass|Converter)\b/).find()
+    def isConcreteAttributeConverter = (source =~ 
/(?s)\bimplements\b.*?\bAttributeConverter\s*</).find()
+            && !(source =~ 
/(?m)^\s*(public\s+|protected\s+|private\s+)?abstract\s+class\s+/).find()
+    hasManagedAnnotation || isConcreteAttributeConverter
+}
+
+private static String toFullyQualifiedClassName(File javaSource) {
+    def packageMatcher = javaSource.text =~ /(?m)^\s*package\s+([^;]+);/
+    if (!packageMatcher.find()) {
+        return null
+    }
+    "${packageMatcher.group(1)}.${javaSource.name - '.java'}"
+}
+
+private static List<Project> runtimeProjectDependencies(Project moduleProject) 
{
+    def runtimeClasspath = 
moduleProject.configurations.findByName('runtimeClasspath')
+    if (runtimeClasspath == null || !runtimeClasspath.canBeResolved) {
+        return []
+    }
+
+    runtimeClasspath.incoming.resolutionResult.allComponents.collect { 
component ->
+        component.id
+    }.findAll { componentId ->
+        componentId instanceof ProjectComponentIdentifier && 
componentId.projectPath != moduleProject.path
+    }.collect { componentId ->
+        moduleProject.rootProject.project(componentId.projectPath)
+    }.unique().sort { left, right ->
+        left.path <=> right.path
+    }
+}
+
+private static Map<Project, List<String>> managedClassesByProject(Project 
moduleProject) {
+    (runtimeProjectDependencies(moduleProject) + moduleProject).collectEntries 
{ Project candidateProject ->
+        def managedClasses = findJpaManagedClasses(candidateProject)
+        managedClasses.isEmpty() ? [:] : [(candidateProject): managedClasses]
+    }
+}
+
+private static void writePersistenceXml(File outputFile, Map<Project, 
List<String>> classesByProject) {
+    outputFile.parentFile.mkdirs()
+    outputFile.text = """<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+<persistence version="2.0"
+             xmlns="http://java.sun.com/xml/ns/persistence";
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd";>
+
+    <!--  This file is generated by static-weaving.gradle and is only used for 
static weaving.  -->
+    <!--  You can find the runtime configuration in the JPAConfig class.  -->
+    <persistence-unit name="jpa-pu" transaction-type="RESOURCE_LOCAL">
+        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+${classesByProject.collect { Project moduleProject, List<String> 
managedClasses ->
+        """
+        <!--  ${moduleProject.name} module: -->
+${managedClasses.collect { managedClass ->
+            "        <class>${managedClass}</class>"
+        }.join('\n')}"""
+    }.join('\n')}
+
+        <exclude-unlisted-classes>false</exclude-unlisted-classes>
+        <properties>
+            <property name="eclipselink.weaving" value="static"/>
+            <property name="eclipselink.weaving.internal" value="false"/>
+        </properties>
+    </persistence-unit>
+</persistence>
+"""
+}
+
+// Wait until after project evaluation to ensure all plugins and dependencies 
are applied.
 project.afterEvaluate {
-    // Only configure if this is a Java project
     if (!project.plugins.hasPlugin('java')) {
-        logger.info("ℹ Skipping static weaving configuration for non-Java 
project: ${project.name}")
+        logger.info("Skipping static weaving configuration for non-Java 
project: ${project.name}")
         return
     }
 
-    // Check if the module contains JPA entities
-    def persistenceXmlFile = 
file("src/main/resources/jpa/static-weaving/module/${project.name}/persistence.xml")
-    def hasJpaEntities = persistenceXmlFile.exists()
+    def ownManagedClasses = findJpaManagedClasses(project)
+    if (ownManagedClasses.isEmpty()) {
+        logger.info("No JPA managed classes found in ${project.name}, skipping 
static weaving configuration")
+        return
+    }
+
+    logger.info("Configuring EclipseLink static weaving for ${project.name}")
 
-    if (hasJpaEntities) {
-        logger.info("Configuring EclipseLink static weaving for 
${project.name}")
+    def generatedPersistenceXml = 
layout.buildDirectory.file('tmp/compileJava/static-weaving/META-INF/persistence.xml')
+    def generateStaticWeavingPersistenceXml = 
tasks.register('generateStaticWeavingPersistenceXml') {
+        description = 'Generates the EclipseLink static weaving 
persistence.xml from project JPA classes'
+        group = 'build'
 
-        compileJava.doLast {
-            def source = sourceSets.main.java.classesDirectory.get()
+        
inputs.files(project.sourceSets.main.java.srcDirs).withPropertyName('javaSourceRoots')
+        
outputs.file(generatedPersistenceXml).withPropertyName('persistenceXml')
+        outputs.upToDateWhen { false }

Review Comment:
   yes, due to the dependency graph, if anything changes in 1 module, we need 
to make sure all dependent is updated (since we dont want to maintain that 
relation, its easier to rescan)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to