@@ -181,9 +181,18 @@ public static List<Package> parsePomFile(String filePath) {
181181 Document doc = builder .parse (new File (filePath ));
182182 doc .getDocumentElement ().normalize ();
183183
184- // First, parse all properties into a map
185- Map <String , String > properties = parseProperties (doc );
186- logger .info ("Loaded {} properties from pom.xml" , properties .size ());
184+ // First, try to load parent POM properties if there's a parent reference
185+ Map <String , String > properties = new HashMap <>();
186+ Map <String , String > parentProperties = parseParentPomProperties (doc , filePath , factory , builder );
187+ if (parentProperties != null && !parentProperties .isEmpty ()) {
188+ properties .putAll (parentProperties );
189+ logger .info ("Loaded {} properties from parent pom.xml" , parentProperties .size ());
190+ }
191+
192+ // Then parse properties from current POM (these override parent properties)
193+ Map <String , String > currentProperties = parseProperties (doc );
194+ properties .putAll (currentProperties );
195+ logger .info ("Loaded {} properties total ({} from current pom.xml)" , properties .size (), currentProperties .size ());
187196
188197 // Find all <dependency> elements
189198 NodeList dependencyNodes = doc .getElementsByTagName ("dependency" );
@@ -483,6 +492,73 @@ private static Map<String, String> parseProperties(Document doc) {
483492 return properties ;
484493 }
485494
495+ /**
496+ * Parse properties from parent POM if it exists
497+ *
498+ * @param doc current document
499+ * @param currentFilePath path to current pom.xml
500+ * @param factory DocumentBuilderFactory to reuse
501+ * @param builder DocumentBuilder to reuse
502+ * @return map of parent properties or empty map
503+ */
504+ private static Map <String , String > parseParentPomProperties (
505+ Document doc ,
506+ String currentFilePath ,
507+ DocumentBuilderFactory factory ,
508+ DocumentBuilder builder ) {
509+
510+ Map <String , String > parentProperties = new HashMap <>();
511+
512+ try {
513+ // Look for <parent> element
514+ NodeList parentNodes = doc .getElementsByTagName ("parent" );
515+ if (parentNodes .getLength () == 0 ) {
516+ return parentProperties ;
517+ }
518+
519+ Element parentElement = (Element ) parentNodes .item (0 );
520+
521+ // Get relativePath (defaults to ../pom.xml if not specified)
522+ String relativePath = getElementText (parentElement , "relativePath" );
523+ if (relativePath == null || relativePath .isEmpty ()) {
524+ relativePath = "../pom.xml" ;
525+ }
526+
527+ // Resolve parent POM path relative to current POM
528+ Path currentPath = Paths .get (currentFilePath ).toAbsolutePath ().getParent ();
529+ Path parentPath = currentPath .resolve (relativePath ).normalize ();
530+
531+ // Check if parent POM exists
532+ File parentPomFile = parentPath .toFile ();
533+ if (!parentPomFile .exists ()) {
534+ logger .warn ("Parent POM not found at: {}" , parentPath );
535+ return parentProperties ;
536+ }
537+
538+ logger .info ("Found parent POM at: {}" , parentPath );
539+
540+ // Parse parent POM
541+ Document parentDoc = builder .parse (parentPomFile );
542+ parentDoc .getDocumentElement ().normalize ();
543+
544+ // Recursively get parent's parent properties first (grandparent)
545+ Map <String , String > grandparentProperties = parseParentPomProperties (
546+ parentDoc , parentPath .toString (), factory , builder );
547+ if (!grandparentProperties .isEmpty ()) {
548+ parentProperties .putAll (grandparentProperties );
549+ }
550+
551+ // Then get parent's own properties (these override grandparent)
552+ Map <String , String > parentOwnProperties = parseProperties (parentDoc );
553+ parentProperties .putAll (parentOwnProperties );
554+
555+ } catch (Exception e ) {
556+ logger .warn ("Error parsing parent POM: {}" , e .getMessage ());
557+ }
558+
559+ return parentProperties ;
560+ }
561+
486562 /**
487563 * Resolve a property reference like ${spring.version} using the properties map
488564 * Supports nested properties (properties that reference other properties)
0 commit comments