Index: src/main/java/org/apache/maven/plugin/ear/AbstractEarModule.java =================================================================== --- src/main/java/org/apache/maven/plugin/ear/AbstractEarModule.java (revision 1000849) +++ src/main/java/org/apache/maven/plugin/ear/AbstractEarModule.java (working copy) @@ -19,16 +19,17 @@ * under the License. */ +import java.io.IOException; +import java.util.Set; + import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.ear.util.ArtifactRepository; import org.codehaus.plexus.util.xml.XMLWriter; -import java.util.Set; - /** * A base implementation of an {@link EarModule}. - * + * * @author Stephane Nicoll * @version $Id$ */ @@ -80,7 +81,7 @@ /** * Creates an ear module from the artifact. - * + * * @param a the artifact */ public AbstractEarModule( Artifact a ) @@ -156,7 +157,7 @@ /** * Returns the artifact's groupId. - * + * * @return the group Id */ public String getGroupId() @@ -166,7 +167,7 @@ /** * Returns the artifact's Id. - * + * * @return the artifact Id */ public String getArtifactId() @@ -176,7 +177,7 @@ /** * Returns the artifact's classifier. - * + * * @return the artifact classifier */ public String getClassifier() @@ -187,7 +188,7 @@ /** * Returns the bundle directory. If null, the module * is bundled in the root of the EAR. - * + * * @return the custom bundle directory */ public String getBundleDir() @@ -202,7 +203,7 @@ /** * Returns the bundle file name. If null, the artifact's * file name is returned. - * + * * @return the bundle file name */ public String getBundleFileName() @@ -220,7 +221,7 @@ * of the deployment descriptor file for a particular Java EE module. The URI * must specify the full pathname of the deployment descriptor file relative * to the application's root directory. - * + * * @return the alternative deployment descriptor for this module */ public String getAltDeploymentDescriptor() @@ -230,7 +231,7 @@ /** * Specify whether this module should be excluded or not. - * + * * @return true if this module should be skipped, false otherwise */ public boolean isExcluded() @@ -245,8 +246,8 @@ /** * Writes the alternative deployment descriptor if necessary. - * - * @param writer the writer to use + * + * @param writer the writer to use * @param version the java EE version in use */ protected void writeAltDeploymentDescriptor( XMLWriter writer, String version ) @@ -262,8 +263,8 @@ /** * Starts a new {@link #MODULE_ELEMENT} on the specified writer, possibly * including an id attribute. - * - * @param writer the XML writer. + * + * @param writer the XML writer. * @param generateId whether an id should be generated */ protected void startModuleElement( XMLWriter writer, Boolean generateId ) @@ -307,7 +308,7 @@ /** * Cleans the bundle directory so that it might be used * properly. - * + * * @param bundleDir the bundle directory to clean * @return the cleaned bundle directory */ @@ -338,8 +339,8 @@ /** * Specify if the objects are both null or both equal. - * - * @param first the first object + * + * @param first the first object * @param second the second object * @return true if parameters are either both null or equal */ @@ -357,7 +358,7 @@ /** * Sets the URI of the module explicitely for testing purposes. - * + * * @param uri the uri */ void setUri( String uri ) @@ -365,4 +366,12 @@ this.uri = uri; } + + public boolean changeManifestClasspath() + { + return true; + } + public String getLibDir() { + return null; + } } Index: src/main/java/org/apache/maven/plugin/ear/EarModule.java =================================================================== --- src/main/java/org/apache/maven/plugin/ear/EarModule.java (revision 1000849) +++ src/main/java/org/apache/maven/plugin/ear/EarModule.java (working copy) @@ -19,15 +19,16 @@ * under the License. */ +import java.io.IOException; +import java.util.Set; + import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoFailureException; import org.codehaus.plexus.util.xml.XMLWriter; -import java.util.Set; - /** * The ear module interface. - * + * * @author Stephane Nicoll * @version $Id$ */ @@ -39,7 +40,7 @@ *

* Note that this might return null till the * module has been resolved. - * + * * @return the artifact * @see #resolveArtifact(java.util.Set) */ @@ -47,21 +48,21 @@ /** * Returns the URI for this module. - * + * * @return the URI */ public String getUri(); /** * Returns the type associated to the module. - * + * * @return the artifact's type of the module */ public String getType(); /** * Specify whether this module should be excluded or not. - * + * * @return true if this module should be skipped, false otherwise */ public boolean isExcluded(); @@ -72,7 +73,7 @@ *

* Returns null if no configuration was specified so that * defaulting may apply. - * + * * @return true if this module should be bundled unpacked, false otherwise */ public Boolean shouldUnpack(); @@ -82,7 +83,7 @@ * of the deployment descriptor file for a particular Java EE module. The URI * must specify the full pathname of the deployment descriptor file relative * to the application's root directory. - * + * * @return the alternative deployment descriptor for this module * @since JavaEE 5 */ @@ -90,9 +91,9 @@ /** * Appends the XML representation of this module. - * - * @param writer the writer to use - * @param version the version of the application.xml file + * + * @param writer the writer to use + * @param version the version of the application.xml file * @param generateId whether an id should be generated */ public void appendModule( XMLWriter writer, String version, Boolean generateId ); @@ -101,9 +102,9 @@ * Resolves the {@link Artifact} represented by the module. Note * that the {@link EarExecutionContext} might be used to customiz * further the resolution. - * + * * @param artifacts the project's artifacts - * @throws EarPluginException if the artifact could not be resolved + * @throws EarPluginException if the artifact could not be resolved * @throws MojoFailureException if an unexpected error occured */ public void resolveArtifact( Set artifacts ) @@ -111,4 +112,8 @@ public void setEarExecutionContext( EarExecutionContext earExecutionContext ); + public boolean changeManifestClasspath(); + + public String getLibDir(); + } Index: src/main/java/org/apache/maven/plugin/ear/EarMojo.java =================================================================== --- src/main/java/org/apache/maven/plugin/ear/EarMojo.java (revision 1000849) +++ src/main/java/org/apache/maven/plugin/ear/EarMojo.java (working copy) @@ -19,8 +19,24 @@ * under the License. */ +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; + import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.archiver.MavenArchiver; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -33,22 +49,24 @@ import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.UnArchiver; import org.codehaus.plexus.archiver.jar.JarArchiver; +import org.codehaus.plexus.archiver.jar.Manifest; +import org.codehaus.plexus.archiver.jar.Manifest.Attribute; +import org.codehaus.plexus.archiver.jar.ManifestException; import org.codehaus.plexus.archiver.manager.ArchiverManager; import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; +import org.codehaus.plexus.archiver.zip.ZipArchiver; +import org.codehaus.plexus.archiver.zip.ZipUnArchiver; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.CollectionUtils; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - /** * Builds J2EE Enteprise Archive (EAR) files. - * + * * @author Stephane Nicoll * @version $Id$ * @goal ear @@ -59,213 +77,227 @@ public class EarMojo extends AbstractEarMojo { - private static final String[] EMPTY_STRING_ARRAY = { }; + private static final String[] EMPTY_STRING_ARRAY = {}; - /** - * Single directory for extra files to include in the EAR. - * - * @parameter expression="${basedir}/src/main/application" - * @required - */ - private File earSourceDirectory; + /** + * Single directory for extra files to include in the EAR. + * + * @parameter expression="${basedir}/src/main/application" + * @required + */ + private File earSourceDirectory; - /** - * The comma separated list of tokens to include in the EAR. - * - * @parameter alias="includes" default-value="**" - */ - private String earSourceIncludes; + /** + * The comma separated list of tokens to include in the EAR. + * + * @parameter alias="includes" default-value="**" + */ + private String earSourceIncludes; - /** - * The comma separated list of tokens to exclude from the EAR. - * - * @parameter alias="excludes" - */ - private String earSourceExcludes; + /** + * The comma separated list of tokens to exclude from the EAR. + * + * @parameter alias="excludes" + */ + private String earSourceExcludes; - /** - * Specify that the ear sources should be filtered. - * - * @parameter default-value="false" - * @since 2.3.2 - */ - private boolean filtering; + /** + * Specify that the ear sources should be filtered. + * + * @parameter default-value="false" + * @since 2.3.2 + */ + private boolean filtering; - /** + /** * Filters (property files) to include during the interpolation of the pom.xml. - * - * @parameter - * @since 2.3.2 - */ - private List filters; + * + * @parameter + * @since 2.3.2 + */ + private List filters; - /** + /** * A list of file extensions that should not be filtered if * filtering is actived. - * - * @parameter - * @since 2.3.2 - */ - private List nonFilteredFileExtensions; + * + * @parameter + * @since 2.3.2 + */ + private List nonFilteredFileExtensions; - /** + /** * To escape interpolated value with windows path * c:\foo\bar will be replaced with c:\\foo\\bar - * + * * @parameter expression="${maven.ear.escapedBackslashesInFilePath}" default-value="false" - * @since 2.3.2 - */ - private boolean escapedBackslashesInFilePath; + * @since 2.3.2 + */ + private boolean escapedBackslashesInFilePath; - /** + /** * Expression preceded with the String won't be interpolated * \${foo} will be replaced with ${foo} - * - * @parameter expression="${maven.ear.escapeString}" - * @since 2.3.2 - */ - protected String escapeString; + * + * @parameter expression="${maven.ear.escapeString}" + * @since 2.3.2 + */ + protected String escapeString; - /** + /** * The location of the manifest file to be used within the ear file. If * not value if specified, the default location in the workDirectory is * taken. If the file does not exist, a manifest will be generated * automatically. - * - * @parameter - */ - private File manifestFile; + * + * @parameter + */ + private File manifestFile; - /** + /** * The location of a custom application.xml file to be used * within the ear file. - * - * @parameter - */ - private String applicationXml; + * + * @parameter + */ + private String applicationXml; - /** - * The directory for the generated EAR. - * - * @parameter expression="${project.build.directory}" - * @required - */ - private String outputDirectory; + /** + * The directory for the generated EAR. + * + * @parameter expression="${project.build.directory}" + * @required + */ + private String outputDirectory; - /** - * The name of the EAR file to generate. - * - * @parameter alias="earName" expression="${project.build.finalName}" - * @required - */ - private String finalName; + /** + * The name of the EAR file to generate. + * + * @parameter alias="earName" expression="${project.build.finalName}" + * @required + */ + private String finalName; - /** + /** * The comma separated list of artifact's type(s) to unpack * by default. - * - * @parameter - */ - private String unpackTypes; + * + * @parameter + */ + private String unpackTypes; - /** - * Classifier to add to the artifact generated. If given, the artifact will - * be an attachment instead. - * - * @parameter - */ - private String classifier; + /** + * Classifier to add to the artifact generated. If given, the artifact will + * be an attachment instead. + * + * @parameter + */ + private String classifier; - /** - * The directory to get the resources from. - * - * @parameter - * @deprecated please use earSourcesDirectory instead - */ - private File resourcesDir; + /** + * The directory to get the resources from. + * + * @parameter + * @deprecated please use earSourcesDirectory instead + */ + private File resourcesDir; - /** - * The Jar archiver. - * - * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="jar" - */ - private JarArchiver jarArchiver; + /** + * The Jar archiver. + * + * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="jar" + */ + private JarArchiver jarArchiver; + /** + * The Zip Un archiver. + * + * @component role="org.codehaus.plexus.archiver.UnArchiver" role-hint="zip" + */ + private ZipUnArchiver zipUnArchiver; + + /** + * The Zip archiver. + * + * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="zip" + */ + private ZipArchiver zipArchiver; + /** * The archive configuration to use. * See Maven Archiver Reference. - * - * @parameter - */ - private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); + * + * @parameter + */ + private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); - /** - * @component - */ - private MavenProjectHelper projectHelper; + /** + * @component + */ + private MavenProjectHelper projectHelper; - /** - * The archive manager. - * - * @component - */ - private ArchiverManager archiverManager; + /** + * The archive manager. + * + * @component + */ + private ArchiverManager archiverManager; - /** + /** * @component role="org.apache.maven.shared.filtering.MavenFileFilter" role-hint="default" - * @required - */ - private MavenFileFilter mavenFileFilter; + * @required + */ + private MavenFileFilter mavenFileFilter; - /** + /** * @component role="org.apache.maven.shared.filtering.MavenResourcesFiltering" role-hint="default" - * @required - */ - private MavenResourcesFiltering mavenResourcesFiltering; + * @required + */ + private MavenResourcesFiltering mavenResourcesFiltering; - /** - * @parameter expression="${session}" - * @readonly - * @required - * @since 2.3.2 - */ - private MavenSession session; + /** + * @parameter expression="${session}" + * @readonly + * @required + * @since 2.3.2 + */ + private MavenSession session; - private List filterWrappers; + private List filterWrappers; public void execute() throws MojoExecutionException, MojoFailureException { - // Initializes ear modules - super.execute(); + // Initializes ear modules + super.execute(); - // Initializes unpack types - List unpackTypesList = new ArrayList(); + // Initializes unpack types + List unpackTypesList = new ArrayList(); if ( unpackTypes != null ) { - unpackTypesList = Arrays.asList( unpackTypes.split( "," ) ); - final Iterator it = unpackTypesList.iterator(); + unpackTypesList = Arrays.asList(unpackTypes.split(",")); + final Iterator it = unpackTypesList.iterator(); while ( it.hasNext() ) { - String type = (String) it.next(); + String type = (String) it.next(); if ( !EarModuleFactory.standardArtifactTypes.contains( type ) ) { throw new MojoExecutionException( "Invalid type[" + type + "] supported types are " + EarModuleFactory.standardArtifactTypes ); - } - } - getLog().debug( "Initialized unpack types " + unpackTypesList ); - } + } + } + getLog().debug("Initialized unpack types " + unpackTypesList); + } - // Copy modules + // Copy modules try { for ( Iterator iter = getModules().iterator(); iter.hasNext(); ) { - EarModule module = (EarModule) iter.next(); + EarModule module = (EarModule) iter.next(); if ( module instanceof JavaModule ) { getLog().warn( "JavaModule is deprecated (" + module + "), please use JarModule instead." ); @@ -273,137 +305,140 @@ if ( module instanceof Ejb3Module ) { getLog().warn( "Ejb3Module is deprecated (" + module + "), please use EjbModule instead." ); - } - final File sourceFile = module.getArtifact().getFile(); + } + final File sourceFile = module.getArtifact().getFile(); final File destinationFile = buildDestinationFile( getWorkDirectory(), module.getUri() ); if ( !sourceFile.isFile() ) { - throw new MojoExecutionException( + throw new MojoExecutionException( "Cannot copy a directory: " + sourceFile.getAbsolutePath() + "; Did you package/install " + module.getArtifact() + "?" ); - } + } if ( destinationFile.getCanonicalPath().equals( sourceFile.getCanonicalPath() ) ) { - getLog().info( + getLog().info( "Skipping artifact[" + module + "], as it already exists at[" + module.getUri() + "]" ); - continue; - } + continue; + } // If the module is within the unpack list, make sure that no unpack wasn't forced (null or true) - // If the module is not in the unpack list, it should be true + // If the module is not in the unpack list, it should be true if ( ( unpackTypesList.contains( module.getType() ) && ( module.shouldUnpack() == null || module.shouldUnpack().booleanValue() ) ) || ( module.shouldUnpack() != null && module.shouldUnpack().booleanValue() ) ) { getLog().info( "Copying artifact[" + module + "] to[" + module.getUri() + "] (unpacked)" ); // Make sure that the destination is a directory to avoid plexus nasty stuff :) - destinationFile.mkdirs(); - unpack( sourceFile, destinationFile ); + destinationFile.mkdirs(); + unpack(sourceFile, destinationFile); } else { if ( sourceFile.lastModified() > destinationFile.lastModified() ) { getLog().info( "Copying artifact[" + module + "] to[" + module.getUri() + "]" ); - FileUtils.copyFile( sourceFile, destinationFile ); + FileUtils.copyFile(sourceFile, destinationFile); } else { - getLog().debug( + getLog().debug( "Skipping artifact[" + module + "], as it is already up to date at[" + module.getUri() + "]" ); - } - } - } - } + } + } + + if (module.changeManifestClasspath()) { + changeManifestClasspath(module, destinationFile); + } + } catch ( IOException e ) { - throw new MojoExecutionException( "Error copying EAR modules", e ); + throw new MojoExecutionException("Error copying EAR modules", e); } catch ( ArchiverException e ) { - throw new MojoExecutionException( "Error unpacking EAR modules", e ); + throw new MojoExecutionException("Error unpacking EAR modules", e); } catch ( NoSuchArchiverException e ) { throw new MojoExecutionException( "No Archiver found for EAR modules", e ); - } + } - // Copy source files + // Copy source files try { - File earSourceDir = earSourceDirectory; + File earSourceDir = earSourceDirectory; if ( earSourceDir.exists() ) { getLog().info( "Copy ear sources to " + getWorkDirectory().getAbsolutePath() ); - String[] fileNames = getEarFiles( earSourceDir ); + String[] fileNames = getEarFiles(earSourceDir); for ( int i = 0; i < fileNames.length; i++ ) { copyFile( new File( earSourceDir, fileNames[i] ), new File( getWorkDirectory(), fileNames[i] ) ); - } - } + } + } if ( applicationXml != null && !"".equals( applicationXml ) ) { - //rename to application.xml + // rename to application.xml getLog().info( "Including custom application.xml[" + applicationXml + "]" ); - File metaInfDir = new File( getWorkDirectory(), META_INF ); + File metaInfDir = new File(getWorkDirectory(), META_INF); copyFile( new File( applicationXml ), new File( metaInfDir, "/application.xml" ) ); - } + } } catch ( IOException e ) { - throw new MojoExecutionException( "Error copying EAR sources", e ); + throw new MojoExecutionException("Error copying EAR sources", e); } catch ( MavenFilteringException e ) { - throw new MojoExecutionException( "Error filtering EAR sources", e ); - } + throw new MojoExecutionException("Error filtering EAR sources", e); + } - // Copy resources files + // Copy resources files try { if ( resourcesDir != null && resourcesDir.exists() ) { getLog().warn( "resourcesDir is deprecated. Please use the earSourceDirectory property instead." ); getLog().info( "Copy ear resources to " + getWorkDirectory().getAbsolutePath() ); - String[] fileNames = getEarFiles( resourcesDir ); + String[] fileNames = getEarFiles(resourcesDir); for ( int i = 0; i < fileNames.length; i++ ) { - FileUtils.copyFile( new File( resourcesDir, fileNames[i] ), - new File( getWorkDirectory(), fileNames[i] ) ); - } - } + FileUtils.copyFile(new File(resourcesDir, fileNames[i]), + new File(getWorkDirectory(), fileNames[i])); + } + } } catch ( IOException e ) { - throw new MojoExecutionException( "Error copying EAR resources", e ); - } + throw new MojoExecutionException("Error copying EAR resources", e); + } - // Check if deployment descriptor is there - File ddFile = new File( getWorkDirectory(), APPLICATION_XML_URI ); + // Check if deployment descriptor is there + File ddFile = new File(getWorkDirectory(), APPLICATION_XML_URI); if ( !ddFile.exists() && ( !( version.equals( VERSION_5 ) || version.equals( VERSION_6 ) ) ) ) { throw new MojoExecutionException( "Deployment descriptor: " + ddFile.getAbsolutePath() + " does not exist." ); - } + } try { - File earFile = getEarFile( outputDirectory, finalName, classifier ); - final MavenArchiver archiver = new EarMavenArchiver( getModules() ); - final JarArchiver jarArchiver = getJarArchiver(); + File earFile = getEarFile(outputDirectory, finalName, classifier); + final MavenArchiver archiver = new EarMavenArchiver(getModules()); + final JarArchiver jarArchiver = getJarArchiver(); getLog().debug( "Jar archiver implementation[" + jarArchiver.getClass().getName() + "]" ); - archiver.setArchiver( jarArchiver ); - archiver.setOutputFile( earFile ); + archiver.setArchiver(jarArchiver); + archiver.setOutputFile(earFile); - // Include custom manifest if necessary - includeCustomManifestFile(); + // Include custom manifest if necessary + includeCustomManifestFile(); - archiver.getArchiver().addDirectory( getWorkDirectory() ); - archiver.createArchive( getProject(), archive ); + archiver.getArchiver().addDirectory(getWorkDirectory()); + archiver.createArchive(getProject(), archive); if ( classifier != null ) { @@ -411,70 +446,70 @@ } else { - getProject().getArtifact().setFile( earFile ); - } + getProject().getArtifact().setFile(earFile); + } } catch ( Exception e ) { - throw new MojoExecutionException( "Error assembling EAR", e ); - } - } + throw new MojoExecutionException("Error assembling EAR", e); + } + } public String getApplicationXml() { - return applicationXml; - } + return applicationXml; + } public void setApplicationXml( String applicationXml ) { - this.applicationXml = applicationXml; - } + this.applicationXml = applicationXml; + } - /** + /** * Returns a string array of the excludes to be used * when assembling/copying the ear. - * - * @return an array of tokens to exclude - */ + * + * @return an array of tokens to exclude + */ protected String[] getExcludes() { - List excludeList = new ArrayList( FileUtils.getDefaultExcludesAsList() ); + List excludeList = new ArrayList(FileUtils.getDefaultExcludesAsList()); if ( earSourceExcludes != null && !"".equals( earSourceExcludes ) ) { excludeList.addAll( Arrays.asList( StringUtils.split( earSourceExcludes, "," ) ) ); - } + } - // if applicationXml is specified, omit the one in the source directory + // if applicationXml is specified, omit the one in the source directory if ( getApplicationXml() != null && !"".equals( getApplicationXml() ) ) { - excludeList.add( "**/" + META_INF + "/application.xml" ); - } + excludeList.add("**/" + META_INF + "/application.xml"); + } - return (String[]) excludeList.toArray( EMPTY_STRING_ARRAY ); - } + return (String[]) excludeList.toArray(EMPTY_STRING_ARRAY); + } - /** + /** * Returns a string array of the includes to be used * when assembling/copying the ear. - * - * @return an array of tokens to include - */ + * + * @return an array of tokens to include + */ protected String[] getIncludes() { return StringUtils.split( StringUtils.defaultString( earSourceIncludes ), "," ); - } + } private static File buildDestinationFile( File buildDir, String uri ) { - return new File( buildDir, uri ); - } + return new File(buildDir, uri); + } private void includeCustomManifestFile() { if ( manifestFile == null ) { - manifestFile = new File( getWorkDirectory(), "META-INF/MANIFEST.MF" ); - } + manifestFile = new File(getWorkDirectory(), "META-INF/MANIFEST.MF"); + } if ( !manifestFile.exists() ) { @@ -483,105 +518,105 @@ else { getLog().info( "Including custom manifest file[" + manifestFile + "]" ); - archive.setManifestFile( manifestFile ); - } - } + archive.setManifestFile(manifestFile); + } + } - /** - * Returns the EAR file to generate, based on an optional classifier. - * + /** + * Returns the EAR file to generate, based on an optional classifier. + * * @param basedir the output directory * @param finalName the name of the ear file * @param classifier an optional classifier - * @return the EAR file to generate - */ + * @return the EAR file to generate + */ private static File getEarFile( String basedir, String finalName, String classifier ) { if ( classifier == null ) { - classifier = ""; + classifier = ""; } else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) ) { - classifier = "-" + classifier; - } + classifier = "-" + classifier; + } - return new File( basedir, finalName + classifier + ".ear" ); - } + return new File(basedir, finalName + classifier + ".ear"); + } - /** + /** * Returns a list of filenames that should be copied * over to the destination directory. - * + * * @param sourceDir the directory to be scanned - * @return the array of filenames, relative to the sourceDir - */ + * @return the array of filenames, relative to the sourceDir + */ private String[] getEarFiles( File sourceDir ) { - DirectoryScanner scanner = new DirectoryScanner(); - scanner.setBasedir( sourceDir ); - scanner.setExcludes( getExcludes() ); - scanner.addDefaultExcludes(); + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setBasedir(sourceDir); + scanner.setExcludes(getExcludes()); + scanner.addDefaultExcludes(); - scanner.setIncludes( getIncludes() ); + scanner.setIncludes(getIncludes()); - scanner.scan(); + scanner.scan(); - return scanner.getIncludedFiles(); - } + return scanner.getIncludedFiles(); + } - /** - * Unpacks the module into the EAR structure. - * + /** + * Unpacks the module into the EAR structure. + * * @param source File to be unpacked. * @param destDir Location where to put the unpacked files. - */ - public void unpack( File source, File destDir ) + */ + public void unpack(File source, File destDir) throws NoSuchArchiverException, IOException, ArchiverException { - UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" ); - unArchiver.setSourceFile( source ); - unArchiver.setDestDirectory( destDir ); + UnArchiver unArchiver = archiverManager.getUnArchiver("zip"); + unArchiver.setSourceFile(source); + unArchiver.setDestDirectory(destDir); - // Extract the module - unArchiver.extract(); - } + // Extract the module + unArchiver.extract(); + } - /** + /** * Returns the {@link JarArchiver} implementation used * to package the EAR file. - *

- * By default the archiver is obtained from the Plexus container. - * - * @return the archiver - */ + *

+ * By default the archiver is obtained from the Plexus container. + * + * @return the archiver + */ protected JarArchiver getJarArchiver() { - return jarArchiver; - } + return jarArchiver; + } - private void copyFile( File source, File target ) + private void copyFile(File source, File target) throws MavenFilteringException, IOException, MojoExecutionException { if ( filtering && !isNonFilteredExtension( source.getName() ) ) { - // Silly that we have to do this ourselves + // Silly that we have to do this ourselves if ( target.getParentFile() != null && !target.getParentFile().exists() ) { - target.getParentFile().mkdirs(); - } + target.getParentFile().mkdirs(); + } mavenFileFilter.copyFile( source, target, true, getFilterWrappers(), null ); } else { - FileUtils.copyFile( source, target ); - } - } + FileUtils.copyFile(source, target); + } + } public boolean isNonFilteredExtension( String fileName ) { return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions ); - } + } private List getFilterWrappers() throws MojoExecutionException @@ -590,18 +625,101 @@ { try { - MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution(); - mavenResourcesExecution.setEscapeString( escapeString ); + MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution(); + mavenResourcesExecution.setEscapeString(escapeString); filterWrappers = mavenFileFilter.getDefaultFilterWrappers( project, filters, escapedBackslashesInFilePath, - this.session, mavenResourcesExecution ); + this.session, mavenResourcesExecution); } catch ( MavenFilteringException e ) { getLog().error( "fail to build filering wrappers " + e.getMessage() ); - throw new MojoExecutionException( e.getMessage(), e ); - } - } - return filterWrappers; - } + throw new MojoExecutionException(e.getMessage(), e); + } + } + return filterWrappers; + } + + private void changeManifestClasspath(EarModule module, File destination) + throws MojoFailureException { + try { + + File tempExtractedArtifact = new File(new File( + generatedDescriptorLocation, "temp"), module.getArtifact() + .getArtifactId()); + tempExtractedArtifact.mkdirs(); + zipUnArchiver.setSourceFile(destination); + zipUnArchiver.setDestDirectory(tempExtractedArtifact); + zipUnArchiver.extract(); + + File manifestFile = new File(tempExtractedArtifact, + "META-INF/MANIFEST.MF"); + Manifest mf = new Manifest(new FileReader(manifestFile)); + Attribute classPath = mf.getMainSection() + .getAttribute("Class-Path"); + List classPathElements = new ArrayList(); + + if (classPath != null) { + classPathElements.addAll(Arrays.asList(classPath.getValue() + .split(" "))); + } + else { + classPath = new Attribute("Class-Path", ""); + mf.getMainSection().addConfiguredAttribute(classPath); + } + + // modify manifest + for (Iterator iter = getModules().iterator(); iter.hasNext();) { + Object o = iter.next(); + + if (o instanceof JarModule) { + JarModule jm = (JarModule) o; + + if (module.getLibDir() != null) { + File artifact = new File(new File( + tempExtractedArtifact, module.getLibDir()), + jm.getBundleFileName()); + + if (artifact.exists()) { + if (!artifact.delete()) { + getLog().error( + "could not delete '" + artifact + "'"); + } + } + } + + if (classPathElements.contains(jm.getBundleFileName())) { + classPathElements.set(classPathElements.indexOf(jm + .getBundleFileName()), jm.getUri()); + } else { + classPathElements.add(jm.getUri()); + } + } + } + classPath.setValue(StringUtils.join(classPathElements.iterator(), + " ")); + + PrintWriter pw = new PrintWriter(manifestFile); + mf.write(pw); + pw.close(); + + if (!destination.delete()) { + getLog().error("could not delete original artifact file " + destination); + } + + getLog().debug("zipping module"); + zipArchiver.setDestFile(destination); + zipArchiver.addDirectory(tempExtractedArtifact); + zipArchiver.createArchive(); + } catch (ManifestException e) { + throw new MojoFailureException(e.getMessage()); + } catch (ZipException e) { + throw new MojoFailureException(e.getMessage()); + } catch (IOException e) { + throw new MojoFailureException(e.getMessage()); + } catch (ArchiverException e) { + throw new MojoFailureException(e.getMessage()); + } + + } } Index: src/main/java/org/apache/maven/plugin/ear/JarModule.java =================================================================== --- src/main/java/org/apache/maven/plugin/ear/JarModule.java (revision 1000849) +++ src/main/java/org/apache/maven/plugin/ear/JarModule.java (working copy) @@ -26,8 +26,8 @@ import java.util.Set; /** - * The {@link EarModule} implementation for a non J2EE module such as - * third party libraries. + * The {@link EarModule} implementation for a non J2EE module such as third + * party libraries. *

* Such module is not incorporated in the generated application.xml * but some application servers support it. To include it in the generated @@ -35,66 +35,63 @@ * boolean flag. *

* This class deprecates {@link org.apache.maven.plugin.ear.JavaModule}. - * + * * @author Stephane Nicoll * @version $Id$ */ -public class JarModule - extends AbstractEarModule -{ - private Boolean includeInApplicationXml = Boolean.FALSE; +public class JarModule extends AbstractEarModule { + private Boolean includeInApplicationXml = Boolean.FALSE; - public JarModule() - { - super(); - } + public JarModule() { + super(); + } - public JarModule( Artifact a, String defaultLibBundleDir, Boolean includeInApplicationXml ) - { - super( a ); - setLibBundleDir( defaultLibBundleDir ); - this.includeInApplicationXml = includeInApplicationXml; + public JarModule(Artifact a, String defaultLibBundleDir, + Boolean includeInApplicationXml) { + super(a); + setLibBundleDir(defaultLibBundleDir); + this.includeInApplicationXml = includeInApplicationXml; - } + } - public void appendModule( XMLWriter writer, String version, Boolean generateId ) - { - // Generates an entry in the application.xml only if - // includeInApplicationXml is set - if ( includeInApplicationXml.booleanValue() ) - { - startModuleElement( writer, generateId ); - writer.startElement( JAVA_MODULE ); - writer.writeText( getUri() ); - writer.endElement(); + public void appendModule(XMLWriter writer, String version, + Boolean generateId) { + // Generates an entry in the application.xml only if + // includeInApplicationXml is set + if (includeInApplicationXml.booleanValue()) { + startModuleElement(writer, generateId); + writer.startElement(JAVA_MODULE); + writer.writeText(getUri()); + writer.endElement(); - writeAltDeploymentDescriptor( writer, version ); + writeAltDeploymentDescriptor(writer, version); - writer.endElement(); - } - } + writer.endElement(); + } + } - public void resolveArtifact( Set artifacts ) - throws EarPluginException, MojoFailureException - { - // Let's resolve the artifact - super.resolveArtifact( artifacts ); + public void resolveArtifact(Set artifacts) throws EarPluginException, + MojoFailureException { + // Let's resolve the artifact + super.resolveArtifact(artifacts); - // If the defaultLibBundleDir is set and no bundle dir is - // set, set the default as bundle dir - setLibBundleDir( earExecutionContext.getDefaultLibBundleDir() ); - } + // If the defaultLibBundleDir is set and no bundle dir is + // set, set the default as bundle dir + setLibBundleDir(earExecutionContext.getDefaultLibBundleDir()); + } - public String getType() - { - return "jar"; - } + public String getType() { + return "jar"; + } - private void setLibBundleDir( String defaultLibBundleDir ) - { - if ( defaultLibBundleDir != null && bundleDir == null ) - { - this.bundleDir = defaultLibBundleDir; - } - } + private void setLibBundleDir(String defaultLibBundleDir) { + if (defaultLibBundleDir != null && bundleDir == null) { + this.bundleDir = defaultLibBundleDir; + } + } + + public boolean changeManifestClasspath() { + return false; + } + } Index: src/main/java/org/apache/maven/plugin/ear/WebModule.java =================================================================== --- src/main/java/org/apache/maven/plugin/ear/WebModule.java (revision 1000849) +++ src/main/java/org/apache/maven/plugin/ear/WebModule.java (working copy) @@ -19,15 +19,15 @@ * under the License. */ +import java.util.Set; + import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoFailureException; import org.codehaus.plexus.util.xml.XMLWriter; -import java.util.Set; - /** * The {@link EarModule} implementation for a Web application module. - * + * * @author Stephane Nicoll * @version $Id$ */ @@ -84,12 +84,12 @@ } } + /** * Returns the context root to use for the web module. *

- * Note that this might return null till the - * artifact has been resolved. - * + * Note that this might return null till the artifact has been resolved. + * * @return the context root */ public String getContextRoot() @@ -103,9 +103,8 @@ } /** - * Generates a default context root for the given artifact, based - * on the artifactId. - * + * Generates a default context root for the given artifact, based on the artifactId. + * * @param a the artifact * @return a context root for the artifact */ @@ -117,4 +116,8 @@ } return "/" + a.getArtifactId(); } + + public String getLibDir() { + return "WEB-INF/lib"; + } }