Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow to create war archive without copying massive files to exploded… #21

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 51 additions & 11 deletions src/main/java/org/apache/maven/plugins/war/AbstractWarMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.apache.maven.plugins.war.packaging.WarPackagingContext;
import org.apache.maven.plugins.war.packaging.WarPackagingTask;
import org.apache.maven.plugins.war.packaging.WarProjectPackagingTask;
import org.apache.maven.plugins.war.util.WarResourceCopy;
import org.apache.maven.plugins.war.util.WebappStructure;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.filtering.MavenFileFilter;
Expand Down Expand Up @@ -373,6 +374,15 @@ public abstract class AbstractWarMojo
@Parameter( defaultValue = "WEB-INF/lib/" )
private String outdatedCheckPath;

/**
* You can skip the exploded war creation when building the war archive.
* War archive are created based on the source paths.
*
* @since 3.3.3
*/
@Parameter( defaultValue = "false", name = "maven.war.exploded.skip" )
private boolean skipExplodedWarCreation;

private final Overlay currentProjectOverlay = Overlay.createInstance();

/**
Expand Down Expand Up @@ -421,6 +431,16 @@ protected String[] getIncludes()
return StringUtils.split( StringUtils.defaultString( warSourceIncludes ), "," );
}

/**
* For mojos want to enable skipExplodedWarCreation, override this method
*
* @return
*/
protected boolean supportSkipExplodedWarCreation()
{
return false;
}

/**
* Returns a string array of the excludes to be used when adding dependent WAR as an overlay onto this WAR.
*
Expand All @@ -446,14 +466,15 @@ protected String[] getDependentWarIncludes()
* @throws MojoExecutionException In case of failure.
* @throws MojoFailureException In case of failure.
*/
public void buildExplodedWebapp( File webapplicationDirectory )
public WarPackagingContext buildExplodedWebapp( File webapplicationDirectory )
throws MojoExecutionException, MojoFailureException
{
skipExplodedWarCreation = supportSkipExplodedWarCreation() ? skipExplodedWarCreation : false;
webapplicationDirectory.mkdirs();

try
{
buildWebapp( project, webapplicationDirectory );
return buildWebapp( project, webapplicationDirectory );
}
catch ( IOException e )
{
Expand All @@ -471,7 +492,7 @@ public void buildExplodedWebapp( File webapplicationDirectory )
* @throws MojoFailureException if an unexpected error occurred while packaging the webapp
* @throws IOException if an error occurred while copying the files
*/
public void buildWebapp( MavenProject mavenProject, File webapplicationDirectory )
public WarPackagingContext buildWebapp( MavenProject mavenProject, File webapplicationDirectory )
throws MojoExecutionException, MojoFailureException, IOException
{

Expand Down Expand Up @@ -524,7 +545,7 @@ public void buildWebapp( MavenProject mavenProject, File webapplicationDirectory
new DefaultWarPackagingContext( webapplicationDirectory, structure, overlayManager, defaultFilterWrappers,
getNonFilteredFileExtensions(), filteringDeploymentDescriptors,
this.artifactFactory, resourceEncoding, useJvmChmod, failOnMissingWebXml,
outputTimestamp );
skipExplodedWarCreation, outputTimestamp );

final List<WarPackagingTask> packagingTasks = getPackagingTasks( overlayManager );

Expand All @@ -534,7 +555,7 @@ public void buildWebapp( MavenProject mavenProject, File webapplicationDirectory
}

getLog().debug( "Webapp assembled in [" + ( System.currentTimeMillis() - startTime ) + " msecs]" );

return context;
}

/**
Expand Down Expand Up @@ -586,6 +607,10 @@ private class DefaultWarPackagingContext

private final List<FileUtils.FilterWrapper> filterWrappers;

private final boolean skipExplodedWarCreation;

private final WarResourceCopy warResourceCopy;

private List<String> nonFilteredFileExtensions;

private boolean filteringDeploymentDescriptors;
Expand All @@ -609,21 +634,25 @@ private class DefaultWarPackagingContext
* @param resourceEncoding The resource encoding.
* @param useJvmChmod use Jvm chmod or not.
* @param failOnMissingWebXml Flag to check whether we should ignore missing web.xml or not
* @param skipExplodedWarCreation
* @param outputTimestamp the output timestamp for reproducible archive creation
*/
DefaultWarPackagingContext( final File webappDirectory, final WebappStructure webappStructure,
final OverlayManager overlayManager,
List<FileUtils.FilterWrapper> filterWrappers,
List<String> nonFilteredFileExtensions,
boolean filteringDeploymentDescriptors, ArtifactFactory artifactFactory,
String resourceEncoding, boolean useJvmChmod,
final Boolean failOnMissingWebXml, String outputTimestamp )
final OverlayManager overlayManager,
List<FileUtils.FilterWrapper> filterWrappers,
List<String> nonFilteredFileExtensions,
boolean filteringDeploymentDescriptors, ArtifactFactory artifactFactory,
String resourceEncoding, boolean useJvmChmod,
final Boolean failOnMissingWebXml, boolean skipExplodedWarCreation,
String outputTimestamp )
{
this.webappDirectory = webappDirectory;
this.webappStructure = webappStructure;
this.overlayManager = overlayManager;
this.filterWrappers = filterWrappers;
this.artifactFactory = artifactFactory;
this.skipExplodedWarCreation = skipExplodedWarCreation;
this.warResourceCopy = new WarResourceCopy( skipExplodedWarCreation );
this.filteringDeploymentDescriptors = filteringDeploymentDescriptors;
this.nonFilteredFileExtensions =
nonFilteredFileExtensions == null ? Collections.<String>emptyList() : nonFilteredFileExtensions;
Expand Down Expand Up @@ -743,6 +772,17 @@ public String[] getWebappSourceExcludes()
return getExcludes();
}

public boolean skipExplodedWarCreation()
{
return skipExplodedWarCreation;
}

@Override
public WarResourceCopy getWarResourceCopy()
{
return warResourceCopy;
}

@Override
public boolean isWebappSourceIncludeEmptyDirectories()
{
Expand Down
89 changes: 75 additions & 14 deletions src/main/java/org/apache/maven/plugins/war/WarMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@
* under the License.
*/

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;

import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
Expand All @@ -37,15 +29,31 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.plugins.war.packaging.AbstractWarPackagingTask;
import org.apache.maven.plugins.war.packaging.WarPackagingContext;
import org.apache.maven.plugins.war.util.ClassesPackager;
import org.apache.maven.plugins.war.util.SourceTargetMappingResourceFilter;
import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.jar.ManifestException;
import org.codehaus.plexus.archiver.war.WarArchiver;
import org.codehaus.plexus.components.io.resources.PlexusIoResource;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Build a WAR file.
*
Expand Down Expand Up @@ -155,10 +163,18 @@ public class WarMojo
@Parameter( property = "maven.war.skip", defaultValue = "false" )
private boolean skip;


// ----------------------------------------------------------------------
// Implementation
// ----------------------------------------------------------------------


@Override
protected boolean supportSkipExplodedWarCreation()
{
return true;
}

/**
* Executes the WarMojo on the current project.
*
Expand Down Expand Up @@ -209,7 +225,7 @@ private void performPackaging( File warFile )
{
getLog().info( "Packaging webapp" );

buildExplodedWebapp( getWebappDirectory() );
WarPackagingContext context = buildExplodedWebapp( getWebappDirectory() );

MavenArchiver archiver = new MavenArchiver();

Expand All @@ -226,16 +242,48 @@ private void performPackaging( File warFile )
+ " from the generated webapp archive." );
getLog().debug( "Including " + Arrays.asList( getPackagingIncludes() ) + " in the generated webapp archive." );

warArchiver.addDirectory( getWebappDirectory(), getPackagingIncludes(), getPackagingExcludes() );

final File webXmlFile = new File( getWebappDirectory(), "WEB-INF/web.xml" );
if ( webXmlFile.exists() )
{
warArchiver.setWebxml( webXmlFile );
}

warArchiver.setRecompressAddedZips( isRecompressZippedFiles() );
if ( context.skipExplodedWarCreation() )
{
Map<String, File> map = context.getWarResourceCopy().getSourceTargetMappings();
if ( map.containsKey( "WEB-INF/web.xml" ) )
{
warArchiver.setWebxml( map.get( "WEB-INF/web.xml" ) );
map.remove( "WEB-INF/web.xml" );
}

SourceTargetMappingResourceFilter filter = new SourceTargetMappingResourceFilter( warArchiver );
Map<String, PlexusIoResource> plexusIoResourceMap =
filter.filteredResources( getPackagingIncludes(), getPackagingExcludes(), "", map );
Iterator<Map.Entry<String, PlexusIoResource>> it = plexusIoResourceMap.entrySet().iterator();
while ( it.hasNext() )
{
Map.Entry<String, PlexusIoResource> rez = it.next();
warArchiver.addResource( rez.getValue(), rez.getKey(), -1 );
}

//copy from exploded war
//case 1: user uses some other plugins to copy files to exploded war
//case 2: copy all filtered files, filtered resources are not tracked and still synced to exploded war
//case 3: web.xml using variables that would be filtered by filteringDeploymentDescriptors
Set<String> targetPaths = context.getWarResourceCopy().getSourceTargetMappings().keySet();
Set<String> newExcludes = new HashSet<>( targetPaths );
newExcludes.addAll( Arrays.asList( getPackagingExcludes() ) );
warArchiver
.addDirectory( getWebappDirectory(), getPackagingIncludes(), newExcludes.toArray( new String[0] ) );
}
else
{
warArchiver.addDirectory( getWebappDirectory(), getPackagingIncludes(), getPackagingExcludes() );
}


warArchiver.setRecompressAddedZips( isRecompressZippedFiles() );
warArchiver.setIncludeEmptyDirs( isIncludeEmptyDirectories() );

if ( Boolean.FALSE.equals( failOnMissingWebXml )
Expand Down Expand Up @@ -265,8 +313,19 @@ private void performPackaging( File warFile )
if ( classesDirectory.exists() )
{
getLog().info( "Packaging classes" );
packager.packageClasses( classesDirectory, getTargetClassesFile(), getJarArchiver(), getSession(),
getProject(), getArchive(), outputTimestamp );
if ( context.skipExplodedWarCreation() )
{
Map<String, File> classes = context.getWarResourceCopy()
.getFilesWithPrefix( AbstractWarPackagingTask.CLASSES_PATH, true );
packager.packageClasses( classes, getTargetClassesFile(), getJarArchiver(), getSession(),
getProject(), getArchive(), outputTimestamp );
}
else
{
packager.packageClasses( classesDirectory, getTargetClassesFile(), getJarArchiver(),
getSession(),
getProject(), getArchive(), outputTimestamp );
}
projectHelper.attachArtifact( getProject(), "jar", getClassesClassifier(), getTargetClassesFile() );
}
}
Expand All @@ -290,6 +349,8 @@ else if ( artifact.getFile() == null || artifact.getFile().isDirectory() )
}
}



/**
* Determines if the current Maven project being built uses the Servlet 3.0 API (JSR 315)
* or Jakarta Servlet API.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@
* under the License.
*/

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.input.XmlStreamReader;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
Expand All @@ -37,6 +34,9 @@
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;

import java.io.File;
import java.io.IOException;

/**
* @author Stephane Nicoll
*/
Expand Down Expand Up @@ -105,6 +105,7 @@ protected void copyFiles( String sourceId, WarPackagingContext context, File sou
destinationFileName = targetPrefix + fileToCopyName;
}


if ( filtered && !context.isNonFilteredExtension( sourceFile.getName() ) )
{
copyFilteredFile( sourceId, context, sourceFile, destinationFileName );
Expand Down Expand Up @@ -283,6 +284,7 @@ protected boolean copyFilteredFile( String sourceId, final WarPackagingContext c
}
}


/**
* Unpacks the specified file to the specified directory.
*
Expand Down Expand Up @@ -336,6 +338,7 @@ protected boolean copyFile( WarPackagingContext context, File source, File desti
throws IOException
{
context.addResource( targetFilename );
context.getWarResourceCopy().addFileCopy( targetFilename, source );

if ( onlyIfModified && destination.lastModified() >= source.lastModified() )
{
Expand Down Expand Up @@ -366,21 +369,20 @@ protected boolean copyFile( WarPackagingContext context, File source, File desti
}
else
{
FileUtils.copyFile( source.getCanonicalFile(), destination );
// preserve timestamp
destination.setLastModified( source.lastModified() );
context.getWarResourceCopy().copy( source, destination );
context.getLog().debug( " + " + targetFilename + " has been copied." );
}
return true;
}
}


/**
* Get the encoding from an XML-file.
*
* @param webXml the XML-file
* @return The encoding of the XML-file, or UTF-8 if it's not specified in the file
* @throws java.io.IOException if an error occurred while reading the file
* @throws IOException if an error occurred while reading the file
*/
protected String getEncoding( File webXml )
throws IOException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,14 @@ protected void generateJarArchive( WarPackagingContext context )
+ ":" + artifact.getArtifactId() + ":" + artifact.getVersion() + "]", e );
}
final String targetFilename = LIB_PATH + archiveName;
final File libDirectory = new File( context.getWebappDirectory(), LIB_PATH );
final File jarFile = new File( libDirectory, archiveName );

if ( context.getWebappStructure().registerFile( currentProjectOverlay.getId(), targetFilename ) )
{
context.addResource( targetFilename );
context.getWarResourceCopy().addFileCopy( targetFilename, jarFile );

final File libDirectory = new File( context.getWebappDirectory(), LIB_PATH );
final File jarFile = new File( libDirectory, archiveName );
final ClassesPackager packager = new ClassesPackager();
packager.packageClasses( context.getClassesDirectory(), jarFile, context.getJarArchiver(),
context.getSession(), project, context.getArchive(),
Expand Down
Loading