From 0e315442d679cb228ba0ee6e6591b9f3e64b7e92 Mon Sep 17 00:00:00 2001 From: Seth Wilcox Date: Fri, 1 Jul 2022 12:57:25 -0600 Subject: [PATCH] Add option to allow forcing resources to be overwritten when they are readonly, similar to ant's force option for file operations --- .../maven/plugins/war/AbstractWarMojo.java | 19 +++++- .../packaging/AbstractWarPackagingTask.java | 4 ++ .../war/packaging/WarPackagingContext.java | 6 ++ .../plugins/war/WarExplodedMojoTest.java | 59 +++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/maven/plugins/war/AbstractWarMojo.java b/src/main/java/org/apache/maven/plugins/war/AbstractWarMojo.java index dc1ecb36..c0876e5b 100644 --- a/src/main/java/org/apache/maven/plugins/war/AbstractWarMojo.java +++ b/src/main/java/org/apache/maven/plugins/war/AbstractWarMojo.java @@ -137,6 +137,11 @@ public abstract class AbstractWarMojo @Parameter private Resource[] webResources; + /** + * If resources should be overwritten, even if they are read only + */ + @Parameter( defaultValue = "false" ) + boolean forceOverwriteResources; /** * Filters (property files) to include during the interpolation of the pom.xml. */ @@ -524,7 +529,7 @@ public void buildWebapp( MavenProject mavenProject, File webapplicationDirectory new DefaultWarPackagingContext( webapplicationDirectory, structure, overlayManager, defaultFilterWrappers, getNonFilteredFileExtensions(), filteringDeploymentDescriptors, this.artifactFactory, resourceEncoding, useJvmChmod, failOnMissingWebXml, - outputTimestamp ); + outputTimestamp, forceOverwriteResources ); final List packagingTasks = getPackagingTasks( overlayManager ); @@ -597,6 +602,8 @@ private class DefaultWarPackagingContext private final Collection outdatedResources; private final String outputTimestamp; + + private final boolean forceOverwriteResources; /** * @param webappDirectory The web application directory. @@ -617,7 +624,8 @@ private class DefaultWarPackagingContext List nonFilteredFileExtensions, boolean filteringDeploymentDescriptors, ArtifactFactory artifactFactory, String resourceEncoding, boolean useJvmChmod, - final Boolean failOnMissingWebXml, String outputTimestamp ) + final Boolean failOnMissingWebXml, String outputTimestamp, + boolean forceOverwriteResources ) { this.webappDirectory = webappDirectory; this.webappStructure = webappStructure; @@ -688,6 +696,7 @@ public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) } } this.outputTimestamp = outputTimestamp; + this.forceOverwriteResources = forceOverwriteResources; } protected boolean checkAllPathsForOutdated() @@ -872,6 +881,12 @@ public String getOutputTimestamp() { return outputTimestamp; } + + @Override + public boolean isForceOverwriteResources() + { + return forceOverwriteResources; + } } /** diff --git a/src/main/java/org/apache/maven/plugins/war/packaging/AbstractWarPackagingTask.java b/src/main/java/org/apache/maven/plugins/war/packaging/AbstractWarPackagingTask.java index e230f6cf..8ce2c36e 100644 --- a/src/main/java/org/apache/maven/plugins/war/packaging/AbstractWarPackagingTask.java +++ b/src/main/java/org/apache/maven/plugins/war/packaging/AbstractWarPackagingTask.java @@ -366,6 +366,10 @@ protected boolean copyFile( WarPackagingContext context, File source, File desti } else { + if ( context.isForceOverwriteResources() && destination.exists() && !destination.canWrite() ) + { + destination.setWritable( true ); + } FileUtils.copyFile( source.getCanonicalFile(), destination ); // preserve timestamp destination.setLastModified( source.lastModified() ); diff --git a/src/main/java/org/apache/maven/plugins/war/packaging/WarPackagingContext.java b/src/main/java/org/apache/maven/plugins/war/packaging/WarPackagingContext.java index 29336a23..de4ea16b 100644 --- a/src/main/java/org/apache/maven/plugins/war/packaging/WarPackagingContext.java +++ b/src/main/java/org/apache/maven/plugins/war/packaging/WarPackagingContext.java @@ -250,4 +250,10 @@ public interface WarPackagingContext * @since 3.3.0 */ String getOutputTimestamp(); + + /** + * If files are modified, but the target is readonly, force update. + * @return forceOverwriteResources + */ + boolean isForceOverwriteResources(); } diff --git a/src/test/java/org/apache/maven/plugins/war/WarExplodedMojoTest.java b/src/test/java/org/apache/maven/plugins/war/WarExplodedMojoTest.java index 22ff280d..f01fb62e 100644 --- a/src/test/java/org/apache/maven/plugins/war/WarExplodedMojoTest.java +++ b/src/test/java/org/apache/maven/plugins/war/WarExplodedMojoTest.java @@ -147,6 +147,65 @@ public void testSimpleExplodedWarWTargetPath() expectedWebResourceFile.delete(); } + /** + * @throws Exception in case of an error. + */ + public void testReadOnlyFileInDestinationInExplodedWar() + throws Exception + { + // setup test data + String testId = "SimpleExplodedWar"; + MavenProjectBasicStub project = new MavenProjectBasicStub(); + File webAppSource = createWebAppSource( testId ); + File classesDir = createClassesDir( testId, false ); + File webAppResource = new File( getTestDirectory(), testId + "-resources" ); + File webAppDirectory = new File( getTestDirectory(), testId ); + File sampleResource = new File( webAppResource, "pix/panis_na.jpg" ); + ResourceStub[] resources = new ResourceStub[] { new ResourceStub() }; + + + createFile( sampleResource ); + + File conflictingFile = new File( webAppDirectory, "pix/panis_na.jpg" ); + if (conflictingFile.exists() ) + { + conflictingFile.delete(); + } + + createFile( conflictingFile ); + conflictingFile.setWritable(false); + conflictingFile.setLastModified(System.currentTimeMillis()-100_000); + + assertTrue( "sampeResource not found", sampleResource.exists() ); + + // configure mojo + resources[0].setDirectory( webAppResource.getAbsolutePath() ); + mojo.forceOverwriteResources=true; + + this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); + setVariableValueToObject( mojo, "webResources", resources ); + mojo.execute(); + + // validate operation + File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); + File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); + File expectedWebResourceFile = new File( webAppDirectory, "pix/panis_na.jpg" ); + File expectedWEBINFDir = new File( webAppDirectory, "WEB-INF" ); + File expectedMETAINFDir = new File( webAppDirectory, "META-INF" ); + + assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); + assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); + assertTrue( "resources doesn't exist: " + expectedWebResourceFile, expectedWebResourceFile.exists() ); + assertTrue( "WEB-INF not found", expectedWEBINFDir.exists() ); + assertTrue( "META-INF not found", expectedMETAINFDir.exists() ); + + // house keeping + expectedWebSourceFile.delete(); + expectedWebSource2File.delete(); + expectedWebResourceFile.delete(); + conflictingFile.delete(); + } + /** * @throws Exception in case of an error. */