11/*
22 * Licensed to the Apache Software Foundation (ASF) under one
33 * or more contributor license agreements. See the NOTICE file
4- * distributed with this work for additional information
4+ * distributed with this work for additional debugrmation
55 * regarding copyright ownership. The ASF licenses this file
66 * to you under the Apache License, Version 2.0 (the
77 * "License"); you may not use this file except in compliance
@@ -85,12 +85,6 @@ tasks.register<ShadowJar>("createPolarisSparkJar") {
8585 archiveClassifier = " bundle"
8686 isZip64 = true
8787
88- // include the LICENSE and NOTICE files for the shadow Jar
89- from(projectDir) {
90- include(" LICENSE" )
91- include(" NOTICE" )
92- }
93-
9488 // pack both the source code and dependencies
9589 from(sourceSets.main.get().output)
9690 configurations = listOf (project.configurations.runtimeClasspath.get())
@@ -99,9 +93,96 @@ tasks.register<ShadowJar>("createPolarisSparkJar") {
9993 // The iceberg-spark-runtime plugin is always packaged along with our polaris-spark plugin,
10094 // therefore excluded from the optimization.
10195 minimize { exclude(dependency(" org.apache.iceberg:iceberg-spark-runtime-*.*" )) }
96+
97+ // Always run the license file addition after this task completes
98+ finalizedBy(" addLicenseFilesToJar" )
99+ }
100+
101+ // Post-processing task to add our project's LICENSE and NOTICE files to the jar and remove any
102+ // other LICENSE or NOTICE files that were shaded in.
103+ tasks.register(" addLicenseFilesToJar" ) {
104+ dependsOn(" createPolarisSparkJar" )
105+
106+ doLast {
107+ val shadowTask = tasks.named(" createPolarisSparkJar" , ShadowJar ::class .java).get()
108+ val jarFile = shadowTask.archiveFile.get().asFile
109+ val tempDir =
110+ File (
111+ " ${project.layout.buildDirectory.get().asFile} /tmp/jar-cleanup-${shadowTask.archiveBaseName.get()} -${shadowTask.archiveClassifier.get()} "
112+ )
113+ val projectLicenseFile = File (projectDir, " LICENSE" )
114+ val projectNoticeFile = File (projectDir, " NOTICE" )
115+
116+ // Validate that required license files exist
117+ if (! projectLicenseFile.exists()) {
118+ throw GradleException (" Project LICENSE file not found at: ${projectLicenseFile.absolutePath} " )
119+ }
120+ if (! projectNoticeFile.exists()) {
121+ throw GradleException (" Project NOTICE file not found at: ${projectNoticeFile.absolutePath} " )
122+ }
123+
124+ logger.info(" Processing jar: ${jarFile.absolutePath} " )
125+ logger.info(" Using temp directory: ${tempDir.absolutePath} " )
126+
127+ // Clean up temp directory
128+ if (tempDir.exists()) {
129+ tempDir.deleteRecursively()
130+ }
131+ tempDir.mkdirs()
132+
133+ // Extract the jar
134+ copy {
135+ from(zipTree(jarFile))
136+ into(tempDir)
137+ }
138+
139+ fileTree(tempDir)
140+ .matching {
141+ include(" **/*LICENSE*" )
142+ include(" **/*NOTICE*" )
143+ }
144+ .forEach { file ->
145+ logger.info(" Removing license file: ${file.relativeTo(tempDir)} " )
146+ file.delete()
147+ }
148+
149+ // Remove META-INF/licenses directory if it exists
150+ val licensesDir = File (tempDir, " META-INF/licenses" )
151+ if (licensesDir.exists()) {
152+ licensesDir.deleteRecursively()
153+ logger.info(" Removed META-INF/licenses directory" )
154+ }
155+
156+ // Copy our project's license files to root
157+ copy {
158+ from(projectLicenseFile)
159+ into(tempDir)
160+ }
161+ logger.info(" Added project LICENSE file" )
162+
163+ copy {
164+ from(projectNoticeFile)
165+ into(tempDir)
166+ }
167+ logger.info(" Added project NOTICE file" )
168+
169+ // Delete the original jar
170+ jarFile.delete()
171+
172+ // Create new jar with only project LICENSE and NOTICE files
173+ ant.withGroovyBuilder {
174+ " jar" (" destfile" to jarFile.absolutePath) { " fileset" (" dir" to tempDir.absolutePath) }
175+ }
176+
177+ logger.info(" Recreated jar with only project LICENSE and NOTICE files" )
178+
179+ // Clean up temp directory
180+ tempDir.deleteRecursively()
181+ }
102182}
103183
104- // ensure the ShadowJar job is run for both `assemble` and `build` task
184+ // ensure the shadow jar job (which will automatically run license addition) is run for both
185+ // `assemble` and `build` task
105186tasks.named(" assemble" ) { dependsOn(" createPolarisSparkJar" ) }
106187
107188tasks.named(" build" ) { dependsOn(" createPolarisSparkJar" ) }
0 commit comments