@@ -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,91 @@ 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+ println (" Processing jar: ${jarFile.absolutePath} " )
125+ println (" 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+ include(" META-INF/LICENSE*" )
144+ include(" META-INF/NOTICE*" )
145+ }
146+ .forEach { file ->
147+ println (" Removing license file: ${file.relativeTo(tempDir)} " )
148+ file.delete()
149+ }
150+
151+ // Copy our project's license files to root
152+ copy {
153+ from(projectLicenseFile)
154+ into(tempDir)
155+ }
156+ println (" Added project LICENSE file" )
157+
158+ copy {
159+ from(projectNoticeFile)
160+ into(tempDir)
161+ }
162+ println (" Added project NOTICE file" )
163+
164+ // Delete the original jar
165+ jarFile.delete()
166+
167+ // Create new jar with only project LICENSE and NOTICE files
168+ ant.withGroovyBuilder {
169+ " jar" (" destfile" to jarFile.absolutePath) { " fileset" (" dir" to tempDir.absolutePath) }
170+ }
171+
172+ println (" Recreated jar with only project LICENSE and NOTICE files" )
173+
174+ // Clean up temp directory
175+ tempDir.deleteRecursively()
176+ }
102177}
103178
104- // ensure the ShadowJar job is run for both `assemble` and `build` task
179+ // ensure the shadow jar job (which will automatically run license addition) is run for both
180+ // `assemble` and `build` task
105181tasks.named(" assemble" ) { dependsOn(" createPolarisSparkJar" ) }
106182
107183tasks.named(" build" ) { dependsOn(" createPolarisSparkJar" ) }
0 commit comments