maven-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rfscho...@apache.org
Subject svn commit: r1755643 [2/5] - in /maven/plugins/trunk/maven-ear-plugin/src: main/java/org/apache/maven/plugin/ main/java/org/apache/maven/plugins/ main/java/org/apache/maven/plugins/ear/ main/java/org/apache/maven/plugins/ear/output/ main/java/org/apach...
Date Tue, 09 Aug 2016 19:17:59 GMT
Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarMojo.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarMojo.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarMojo.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,891 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.zip.ZipException;
+
+import org.apache.maven.archiver.MavenArchiveConfiguration;
+import org.apache.maven.archiver.MavenArchiver;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+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.ear.util.EarMavenArchiver;
+import org.apache.maven.plugins.ear.util.JavaEEVersion;
+import org.apache.maven.plugins.ear.util.ModuleIdentifierValidator;
+import org.apache.maven.project.MavenProjectHelper;
+import org.apache.maven.shared.filtering.MavenFileFilter;
+import org.apache.maven.shared.filtering.MavenFilteringException;
+import org.apache.maven.shared.filtering.MavenResourcesExecution;
+import org.apache.maven.shared.filtering.MavenResourcesFiltering;
+import org.apache.maven.shared.utils.io.FileUtils;
+import org.codehaus.plexus.archiver.Archiver;
+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.util.DirectoryScanner;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * Builds J2EE Enterprise Archive (EAR) files.
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: EarMojo.java 1755539 2016-08-08 20:34:46Z rfscholte $
+ */
+// CHECKSTYLE_OFF: LineLength
+@Mojo( name = "ear", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.TEST )
+// CHECKSTYLE_ON: LineLength
+public class EarMojo
+    extends AbstractEarMojo
+{
+    /**
+     * Single directory for extra files to include in the EAR.
+     */
+    @Parameter( defaultValue = "${basedir}/src/main/application", required = true )
+    private File earSourceDirectory;
+
+    /**
+     * The comma separated list of tokens to include in the EAR.
+     */
+    @Parameter( alias = "includes", defaultValue = "**" )
+    private String earSourceIncludes;
+
+    /**
+     * 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.
+     * 
+     * @since 2.3.2
+     */
+    @Parameter( defaultValue = "false" )
+    private boolean filtering;
+
+    /**
+     * Filters (property files) to include during the interpolation of the pom.xml.
+     * 
+     * @since 2.3.2
+     */
+    @Parameter
+    private List<String> filters;
+
+    /**
+     * A list of file extensions that should not be filtered if filtering is enabled.
+     * 
+     * @since 2.3.2
+     */
+    @Parameter
+    private List<String> nonFilteredFileExtensions;
+
+    /**
+     * To escape interpolated value with Windows path c:\foo\bar will be replaced with c:\\foo\\bar.
+     * 
+     * @since 2.3.2
+     */
+    @Parameter( property = "maven.ear.escapedBackslashesInFilePath", defaultValue = "false" )
+    private boolean escapedBackslashesInFilePath;
+
+    /**
+     * Expression preceded with this String won't be interpolated \${foo} will be replaced with ${foo}.
+     * 
+     * @since 2.3.2
+     */
+    @Parameter( property = "maven.ear.escapeString" )
+    protected String escapeString;
+
+    /**
+     * In case of using the {@link #skinnyWars} and {@link #defaultLibBundleDir} usually the
+     * classpath will be modified.
+     * By settings this option {@code true} you can change this and keep the classpath untouched.
+     * This option has been introduced to keep the backward compatibility with earlier versions
+     * of the plugin.
+     * 
+     * @since 2.10
+     */
+    @Parameter( defaultValue = "false" )
+    private boolean skipClassPathModification;
+
+    /**
+     * The location of the manifest file to be used within the EAR file. If no 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;
+
+    /**
+     * The location of a custom application.xml file to be used within the EAR file.
+     */
+    @Parameter
+    private String applicationXml;
+
+    /**
+     * The directory for the generated EAR.
+     */
+    @Parameter( defaultValue = "${project.build.directory}", required = true )
+    private String outputDirectory;
+
+    /**
+     * The name of the EAR file to generate.
+     */
+    @Parameter( alias = "earName", defaultValue = "${project.build.finalName}", required = true )
+    private String finalName;
+
+    /**
+     * The comma separated list of artifact's type(s) to unpack by default.
+     */
+    @Parameter
+    private String unpackTypes;
+
+    /**
+     * Classifier to add to the artifact generated. If given, the artifact will be an attachment instead.
+     */
+    @Parameter
+    private String classifier;
+
+    /**
+     * A comma separated list of tokens to exclude when packaging the EAR. By default nothing is excluded. Note that you
+     * can use the Java Regular Expressions engine to include and exclude specific pattern using the expression
+     * %regex[]. Hint: read the about (?!Pattern).
+     * 
+     * @since 2.7
+     */
+    @Parameter
+    private String packagingExcludes;
+
+    /**
+     * A comma separated list of tokens to include when packaging the EAR. By default everything is included. Note that
+     * you can use the Java Regular Expressions engine to include and exclude specific pattern using the expression
+     * %regex[].
+     * 
+     * @since 2.7
+     */
+    @Parameter
+    private String packagingIncludes;
+
+    /**
+     * Whether to create skinny WARs or not. A skinny WAR is a WAR that does not have all of its dependencies in
+     * WEB-INF/lib. Instead those dependencies are shared between the WARs through the EAR.
+     * 
+     * @since 2.7
+     */
+    @Parameter( property = "maven.ear.skinnyWars", defaultValue = "false" )
+    private boolean skinnyWars;
+
+    /**
+     * The Jar archiver.
+     */
+    @Component( role = Archiver.class, hint = "jar" )
+    private JarArchiver jarArchiver;
+
+    /**
+     * The Zip archiver.
+     */
+    @Component( role = Archiver.class, hint = "zip" )
+    private ZipArchiver zipArchiver;
+
+    /**
+     * The Zip Un archiver.
+     */
+    @Component( role = UnArchiver.class, hint = "zip" )
+    private ZipUnArchiver zipUnArchiver;
+
+    /**
+     * The archive configuration to use. See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven
+     * Archiver Reference</a>.
+     */
+    @Parameter
+    private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
+
+    /**
+     */
+    @Component
+    private MavenProjectHelper projectHelper;
+
+    /**
+     * The archive manager.
+     */
+    @Component
+    private ArchiverManager archiverManager;
+
+    /**
+     */
+    @Component( role = MavenFileFilter.class, hint = "default" )
+    private MavenFileFilter mavenFileFilter;
+
+    /**
+     */
+    @Component( role = MavenResourcesFiltering.class, hint = "default" )
+    private MavenResourcesFiltering mavenResourcesFiltering;
+
+    /**
+     * @since 2.3.2
+     */
+    @Parameter( defaultValue = "${session}", readonly = true, required = true )
+    private MavenSession session;
+
+    private List<FileUtils.FilterWrapper> filterWrappers;
+
+    /**
+     * @since 2.9
+     */
+    @Parameter( property = "maven.ear.useJvmChmod", defaultValue = "true" )
+    private boolean useJvmChmod = true;
+
+    /**
+     * The list of artifacts is checked and if you set this to {@code true} the build will fail if duplicate artifacts
+     * have been found within the build configuration.
+     * 
+     * @since 2.10
+     */
+    // TODO: This can be removed if we change to full unique identifiers in EAR (next major version!)
+    @Parameter( defaultValue = "false", property = "maven.ear.duplicateArtifactsBreakTheBuild" )
+    private boolean duplicateArtifactsBreakTheBuild;
+
+    private void checkModuleUniqueness()
+        throws MojoExecutionException
+    {
+        ModuleIdentifierValidator miv = new ModuleIdentifierValidator( getModules() );
+        miv.checkForDuplicateArtifacts();
+        if ( miv.existDuplicateArtifacts() )
+        {
+            Map<String, List<EarModule>> duplicateArtifacts = miv.getDuplicateArtifacts();
+            for ( Entry<String, List<EarModule>> entry : duplicateArtifacts.entrySet() )
+            {
+                getLog().warn( "The artifactId " + entry.getKey() + " exists more than once in the modules list." );
+                for ( EarModule earModule : entry.getValue() )
+                {
+                    getLog().warn( " --> " + earModule.getArtifact().getId() + " (" + earModule.getType() + ")" );
+                }
+            }
+
+            getLog().warn( "HINT: This can be simply solved by using the <fileNameMapping>full</fileNameMapping>" );
+
+            if ( duplicateArtifactsBreakTheBuild )
+            {
+                // CHECKSTYLE_OFF: LineLength
+                throw new MojoExecutionException(
+                                                  "The build contains duplicate artifacts which result in unpredictable ear content." );
+                // CHECKSTYLE_ON: LineLength
+            }
+        }
+
+    }
+
+    /** {@inheritDoc} */
+    public void execute()
+        throws MojoExecutionException, MojoFailureException
+    {
+        // Initializes ear modules
+        super.execute();
+
+        zipArchiver.setUseJvmChmod( useJvmChmod );
+        zipUnArchiver.setUseJvmChmod( useJvmChmod );
+
+        final JavaEEVersion javaEEVersion = JavaEEVersion.getJavaEEVersion( version );
+
+        // Initializes unpack types
+        List<String> unpackTypesList = createUnpackList();
+
+        // Copy modules
+        copyModules( javaEEVersion, unpackTypesList );
+
+        // Copy source files
+        try
+        {
+            File earSourceDir = earSourceDirectory;
+            if ( earSourceDir.exists() )
+            {
+                getLog().info( "Copy ear sources to " + getWorkDirectory().getAbsolutePath() );
+                String[] fileNames = getEarFiles( earSourceDir );
+                for ( String fileName : fileNames )
+                {
+                    copyFile( new File( earSourceDir, fileName ), new File( getWorkDirectory(), fileName ) );
+                }
+            }
+
+            if ( applicationXml != null && !"".equals( applicationXml ) )
+            {
+                // rename to application.xml
+                getLog().info( "Including custom application.xml[" + applicationXml + "]" );
+                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 );
+        }
+        catch ( MavenFilteringException e )
+        {
+            throw new MojoExecutionException( "Error filtering EAR sources", e );
+        }
+
+        // Check if deployment descriptor is there
+        File ddFile = new File( getWorkDirectory(), APPLICATION_XML_URI );
+        if ( !ddFile.exists() && ( javaEEVersion.lt( JavaEEVersion.FIVE ) ) )
+        {
+            // CHECKSTYLE_OFF: LineLength
+            throw new MojoExecutionException( "Deployment descriptor: " + ddFile.getAbsolutePath() + " does not exist." );
+            // CHECKSTYLE_ON: LineLength
+        }
+
+        try
+        {
+            File earFile = getEarFile( outputDirectory, finalName, classifier );
+            final MavenArchiver archiver = new EarMavenArchiver( getModules() );
+            final JarArchiver theJarArchiver = getJarArchiver();
+            getLog().debug( "Jar archiver implementation [" + theJarArchiver.getClass().getName() + "]" );
+            archiver.setArchiver( theJarArchiver );
+            archiver.setOutputFile( earFile );
+
+            // Include custom manifest if necessary
+            includeCustomManifestFile();
+
+            getLog().debug( "Excluding " + Arrays.asList( getPackagingExcludes() ) + " from the generated EAR." );
+            getLog().debug( "Including " + Arrays.asList( getPackagingIncludes() ) + " in the generated EAR." );
+
+            archiver.getArchiver().addDirectory( getWorkDirectory(), getPackagingIncludes(), getPackagingExcludes() );
+            archiver.createArchive( session, getProject(), archive );
+
+            if ( classifier != null )
+            {
+                projectHelper.attachArtifact( getProject(), "ear", classifier, earFile );
+            }
+            else
+            {
+                getProject().getArtifact().setFile( earFile );
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new MojoExecutionException( "Error assembling EAR", e );
+        }
+    }
+
+    private void copyModules( final JavaEEVersion javaEEVersion, List<String> unpackTypesList )
+        throws MojoExecutionException, MojoFailureException
+    {
+        try
+        {
+            // TODO: With the next major release the modules
+            // should be identified by a unique id instead of the
+            // the artifactId's only which means this
+            // check can be removed.
+            // http://jira.codehaus.org/browse/MEAR-209
+            checkModuleUniqueness();
+
+            for ( EarModule module : getModules() )
+            {
+                final File sourceFile = module.getArtifact().getFile();
+                final File destinationFile = buildDestinationFile( getWorkDirectory(), module.getUri() );
+                if ( !sourceFile.isFile() )
+                {
+                    throw new MojoExecutionException( "Cannot copy a directory: " + sourceFile.getAbsolutePath()
+                        + "; Did you package/install " + module.getArtifact() + "?" );
+                }
+
+                if ( destinationFile.getCanonicalPath().equals( sourceFile.getCanonicalPath() ) )
+                {
+                    getLog().info( "Skipping artifact [" + module + "], as it already exists at [" + module.getUri()
+                                       + "]" );
+                    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
+                // CHECKSTYLE_OFF: LineLength
+                if ( ( unpackTypesList.contains( module.getType() ) && ( module.shouldUnpack() == null || module.shouldUnpack() ) )
+                    || ( module.shouldUnpack() != null && module.shouldUnpack() ) )
+                // CHECKSTYLE_ON: LineLength
+                {
+                    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 );
+
+                    if ( skinnyWars && module.changeManifestClasspath() )
+                    {
+                        changeManifestClasspath( module, destinationFile, javaEEVersion );
+                    }
+                }
+                else
+                {
+                    if ( sourceFile.lastModified() > destinationFile.lastModified() )
+                    {
+                        getLog().info( "Copying artifact [" + module + "] to [" + module.getUri() + "]" );
+                        FileUtils.copyFile( sourceFile, destinationFile );
+
+                        if ( skinnyWars && module.changeManifestClasspath() )
+                        {
+                            changeManifestClasspath( module, destinationFile, javaEEVersion );
+                        }
+                    }
+                    else
+                    {
+                        getLog().debug( "Skipping artifact [" + module + "], as it is already up to date at ["
+                                            + module.getUri() + "]" );
+                    }
+                }
+            }
+        }
+        catch ( IOException e )
+        {
+            throw new MojoExecutionException( "Error copying EAR modules", e );
+        }
+        catch ( ArchiverException e )
+        {
+            throw new MojoExecutionException( "Error unpacking EAR modules", e );
+        }
+        catch ( NoSuchArchiverException e )
+        {
+            throw new MojoExecutionException( "No Archiver found for EAR modules", e );
+        }
+    }
+
+    private List<String> createUnpackList()
+        throws MojoExecutionException
+    {
+        List<String> unpackTypesList = new ArrayList<String>();
+        if ( unpackTypes != null )
+        {
+            unpackTypesList = Arrays.asList( unpackTypes.split( "," ) );
+            for ( String type : unpackTypesList )
+            {
+                if ( !EarModuleFactory.STANDARD_ARTIFACT_TYPE.contains( type ) )
+                {
+                    throw new MojoExecutionException( "Invalid type [" + type + "] supported types are "
+                        + EarModuleFactory.STANDARD_ARTIFACT_TYPE );
+                }
+            }
+            getLog().debug( "Initialized unpack types " + unpackTypesList );
+        }
+        return unpackTypesList;
+    }
+
+    /**
+     * @return {@link #applicationXml}
+     */
+    public String getApplicationXml()
+    {
+        return applicationXml;
+    }
+
+    /**
+     * @param applicationXml {@link #applicationXml}
+     */
+    public void setApplicationXml( String 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
+     */
+    protected String[] getExcludes()
+    {
+        List<String> excludeList = new ArrayList<String>( 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 ( getApplicationXml() != null && !"".equals( getApplicationXml() ) )
+        {
+            excludeList.add( "**/" + META_INF + "/application.xml" );
+        }
+
+        return excludeList.toArray( new String[excludeList.size()] );
+    }
+
+    /**
+     * Returns a string array of the includes to be used when assembling/copying the ear.
+     * 
+     * @return an array of tokens to include
+     */
+    protected String[] getIncludes()
+    {
+        return StringUtils.split( StringUtils.defaultString( earSourceIncludes ), "," );
+    }
+
+    /**
+     * @return The array with the packaging excludes.
+     */
+    public String[] getPackagingExcludes()
+    {
+        if ( StringUtils.isEmpty( packagingExcludes ) )
+        {
+            return new String[0];
+        }
+        else
+        {
+            return StringUtils.split( packagingExcludes, "," );
+        }
+    }
+
+    /**
+     * @param packagingExcludes {@link #packagingExcludes}
+     */
+    public void setPackagingExcludes( String packagingExcludes )
+    {
+        this.packagingExcludes = packagingExcludes;
+    }
+
+    /**
+     * @return The arrays with the includes.
+     */
+    public String[] getPackagingIncludes()
+    {
+        if ( StringUtils.isEmpty( packagingIncludes ) )
+        {
+            return new String[] { "**" };
+        }
+        else
+        {
+            return StringUtils.split( packagingIncludes, "," );
+        }
+    }
+
+    /**
+     * @param packagingIncludes {@link #packagingIncludes}
+     */
+    public void setPackagingIncludes( String packagingIncludes )
+    {
+        this.packagingIncludes = packagingIncludes;
+    }
+
+    private static File buildDestinationFile( File buildDir, String uri )
+    {
+        return new File( buildDir, uri );
+    }
+
+    private void includeCustomManifestFile()
+    {
+        if ( manifestFile == null )
+        {
+            manifestFile = new File( getWorkDirectory(), "META-INF/MANIFEST.MF" );
+        }
+
+        if ( !manifestFile.exists() )
+        {
+            getLog().info( "Could not find manifest file: " + manifestFile + " - Generating one" );
+        }
+        else
+        {
+            getLog().info( "Including custom manifest file [" + manifestFile + "]" );
+            archive.setManifestFile( manifestFile );
+        }
+    }
+
+    /**
+     * 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
+     */
+    private static File getEarFile( String basedir, String finalName, String classifier )
+    {
+        if ( classifier == null )
+        {
+            classifier = "";
+        }
+        else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) )
+        {
+            classifier = "-" + classifier;
+        }
+
+        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
+     */
+    private String[] getEarFiles( File sourceDir )
+    {
+        DirectoryScanner scanner = new DirectoryScanner();
+        scanner.setBasedir( sourceDir );
+        scanner.setExcludes( getExcludes() );
+        scanner.addDefaultExcludes();
+
+        scanner.setIncludes( getIncludes() );
+
+        scanner.scan();
+
+        return scanner.getIncludedFiles();
+    }
+
+    /**
+     * Unpacks the module into the EAR structure.
+     * 
+     * @param source File to be unpacked.
+     * @param destDir Location where to put the unpacked files.
+     * @throws NoSuchArchiverException In case of we don't have an appropriate archiver.
+     * @throws IOException In case of a general IOException.
+     */
+    public void unpack( File source, File destDir )
+        throws NoSuchArchiverException, IOException
+    {
+        UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" );
+        unArchiver.setSourceFile( source );
+        unArchiver.setDestDirectory( destDir );
+
+        // Extract the module
+        unArchiver.extract();
+    }
+
+    /**
+     * Returns the {@link JarArchiver} implementation used to package the EAR file.
+     * <p/>
+     * By default the archiver is obtained from the Plexus container.
+     * 
+     * @return the archiver
+     */
+    protected JarArchiver getJarArchiver()
+    {
+        return jarArchiver;
+    }
+
+    private void copyFile( File source, File target )
+        throws MavenFilteringException, IOException, MojoExecutionException
+    {
+        if ( filtering && !isNonFilteredExtension( source.getName() ) )
+        {
+            // Silly that we have to do this ourselves
+            if ( target.getParentFile() != null && !target.getParentFile().exists() )
+            {
+                target.getParentFile().mkdirs();
+            }
+
+            mavenFileFilter.copyFile( source, target, true, getFilterWrappers(), encoding );
+        }
+        else
+        {
+            FileUtils.copyFile( source, target );
+        }
+    }
+
+    /**
+     * @param fileName The name of the file which should be checked.
+     * @return {@code true} if the name is part of the non filtered extensions {@code false} otherwise.
+     */
+    public boolean isNonFilteredExtension( String fileName )
+    {
+        return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions );
+    }
+
+    private List<FileUtils.FilterWrapper> getFilterWrappers()
+        throws MojoExecutionException
+    {
+        if ( filterWrappers == null )
+        {
+            try
+            {
+                MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
+                mavenResourcesExecution.setMavenProject( getProject() );
+                mavenResourcesExecution.setEscapedBackslashesInFilePath( escapedBackslashesInFilePath );
+                mavenResourcesExecution.setFilters( filters );
+                mavenResourcesExecution.setEscapeString( escapeString );
+
+                filterWrappers = mavenFileFilter.getDefaultFilterWrappers( mavenResourcesExecution );
+            }
+            catch ( MavenFilteringException e )
+            {
+                getLog().error( "Fail to build filtering wrappers " + e.getMessage() );
+                throw new MojoExecutionException( e.getMessage(), e );
+            }
+        }
+        return filterWrappers;
+    }
+
+    private void changeManifestClasspath( EarModule module, File original, JavaEEVersion javaEEVersion )
+        throws MojoFailureException
+    {
+        try
+        {
+            File workDirectory;
+
+            // Handle the case that the destination might be a directory (project-038)
+            if ( original.isFile() )
+            {
+                // Create a temporary work directory
+                // MEAR-167 use uri as directory to prevent merging of artifacts with the same artifactId
+                workDirectory = new File( new File( getTempFolder(), "temp" ), module.getUri() );
+                workDirectory.mkdirs();
+                getLog().debug( "Created a temporary work directory: " + workDirectory.getAbsolutePath() );
+
+                // Unpack the archive to a temporary work directory
+                zipUnArchiver.setSourceFile( original );
+                zipUnArchiver.setDestDirectory( workDirectory );
+                zipUnArchiver.extract();
+            }
+            else
+            {
+                workDirectory = original;
+            }
+
+            // Create a META-INF/MANIFEST.MF file if it doesn't exist (project-038)
+            File metaInfDirectory = new File( workDirectory, "META-INF" );
+            boolean newMetaInfCreated = metaInfDirectory.mkdirs();
+            if ( newMetaInfCreated )
+            {
+                // CHECKSTYLE_OFF: LineLength
+                getLog().debug( "This project did not have a META-INF directory before, so a new directory was created." );
+                // CHECKSTYLE_ON: LineLength
+            }
+            File newCreatedManifestFile = new File( metaInfDirectory, "MANIFEST.MF" );
+            boolean newManifestCreated = newCreatedManifestFile.createNewFile();
+            if ( newManifestCreated )
+            {
+                // CHECKSTYLE_OFF: LineLength
+                getLog().debug( "This project did not have a META-INF/MANIFEST.MF file before, so a new file was created." );
+                // CHECKSTYLE_ON: LineLength
+            }
+
+            // Read the manifest from disk
+            Manifest mf = new Manifest( new FileInputStream( newCreatedManifestFile ) );
+            Attribute classPath = mf.getMainSection().getAttribute( "Class-Path" );
+            List<String> classPathElements = new ArrayList<String>();
+
+            if ( classPath != null )
+            {
+                classPathElements.addAll( Arrays.asList( classPath.getValue().split( " " ) ) );
+            }
+            else
+            {
+                classPath = new Attribute( "Class-Path", "" );
+            }
+
+            // Modify the classpath entries in the manifest
+            for ( EarModule o : getModules() )
+            {
+                if ( o instanceof JarModule )
+                {
+                    JarModule jm = (JarModule) o;
+
+                    if ( module.getLibDir() != null )
+                    {
+                        // MEAR-189:
+                        // We use the original name, cause in case of fileNameMapping to no-version/full
+                        // we could not not delete it and it will end up in the resulting EAR and the WAR
+                        // will not be cleaned up.
+                        File artifact =
+                            new File( new File( workDirectory, module.getLibDir() ), jm.getOriginalBundleFileName() );
+
+                        if ( artifact.exists() )
+                        {
+                            getLog().debug( " -> Artifact to delete: " + artifact );
+                            if ( !artifact.delete() )
+                            {
+                                getLog().error( "Could not delete '" + artifact + "'" );
+                            }
+                        }
+                    }
+
+                    if ( classPathElements.contains( jm.getBundleFileName() ) )
+                    {
+                        classPathElements.set( classPathElements.indexOf( jm.getBundleFileName() ), jm.getUri() );
+                    }
+                    else
+                    {
+                        if ( !skipClassPathModification )
+                        {
+                            classPathElements.add( jm.getUri() );
+                        }
+                        else
+                        {
+                            if ( javaEEVersion.lt( JavaEEVersion.FIVE ) || defaultLibBundleDir == null )
+                            {
+                                classPathElements.add( jm.getUri() );
+                            }
+                        }
+                    }
+                }
+            }
+            classPath.setValue( StringUtils.join( classPathElements.iterator(), " " ) );
+            mf.getMainSection().addConfiguredAttribute( classPath );
+
+            // Write the manifest to disk
+            PrintWriter pw = new PrintWriter( newCreatedManifestFile );
+            mf.write( pw );
+            pw.close();
+
+            if ( original.isFile() )
+            {
+                // Pack up the archive again from the work directory
+                if ( !original.delete() )
+                {
+                    getLog().error( "Could not delete original artifact file " + original );
+                }
+
+                getLog().debug( "Zipping module" );
+                zipArchiver.setDestFile( original );
+                zipArchiver.addDirectory( workDirectory );
+                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() );
+        }
+    }
+}

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarPluginException.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarPluginException.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarPluginException.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EarPluginException.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,68 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * The base exception of the EAR plugin.
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: EarPluginException.java 1645331 2014-12-13 17:31:09Z khmarbaise $
+ */
+public class EarPluginException
+    extends Exception
+{
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -5540929953103327928L;
+
+    /**
+     * Create an instance.
+     */
+    public EarPluginException()
+    {
+    }
+
+    /**
+     * @param message The message for the exception.
+     */
+    public EarPluginException( String message )
+    {
+        super( message );
+    }
+
+    /**
+     * @param cause {@link Throwable}
+     */
+    public EarPluginException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    /**
+     * @param message The message to emit.
+     * @param cause {@link Throwable}
+     */
+    public EarPluginException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbClientModule.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbClientModule.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbClientModule.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbClientModule.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,58 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.artifact.Artifact;
+
+/**
+ * The {@link EarModule} implementation for an ejb client module.
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: EjbClientModule.java 1645331 2014-12-13 17:31:09Z khmarbaise $
+ */
+public class EjbClientModule
+    extends JarModule
+{
+
+    /**
+     * Create an instance.
+     */
+    public EjbClientModule()
+    {
+        super();
+    }
+
+    /**
+     * @param a {@link Artifact}
+     * @param defaultLibBundleDir The default lib bundle directory.
+     */
+    public EjbClientModule( Artifact a, String defaultLibBundleDir )
+    {
+        super( a, defaultLibBundleDir, Boolean.FALSE );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getType()
+    {
+        return "ejb-client";
+    }
+}

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbModule.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbModule.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbModule.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbModule.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,73 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.codehaus.plexus.util.xml.XMLWriter;
+
+/**
+ * The {@link EarModule} implementation for an EJB module.
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: EjbModule.java 1645331 2014-12-13 17:31:09Z khmarbaise $
+ */
+public class EjbModule
+    extends AbstractEarModule
+{
+    private static final String EJB_MODULE = "ejb";
+
+    /**
+     * Create an instance.
+     */
+    public EjbModule()
+    {
+    }
+
+    /**
+     * @param a {@link Artifact}
+     */
+    public EjbModule( Artifact a )
+    {
+        super( a );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void appendModule( XMLWriter writer, String version, Boolean generateId )
+    {
+        startModuleElement( writer, generateId );
+        writer.startElement( EJB_MODULE );
+        writer.writeText( getUri() );
+        writer.endElement();
+
+        writeAltDeploymentDescriptor( writer, version );
+
+        writer.endElement();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getType()
+    {
+        return EJB_MODULE;
+    }
+}

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbRef.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbRef.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbRef.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EjbRef.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,173 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.XMLWriter;
+
+/**
+ * Representation of {@code ejb-ref} element in {@code application.xml} file.
+ * 
+ * @author Karl Heinz Marbaise
+ * @since 2.10
+ */
+public class EjbRef
+{
+    static final String DESCRIPTION = "description";
+
+    static final String EJB_REF = "ejb-ref";
+
+    static final String EJB_NAME = "ejb-ref-name";
+
+    static final String EJB_TYPE = "ejb-ref-type";
+
+    static final String EJB_LOOKUP_NAME = "lookup-name";
+
+    private final String description;
+
+    private String name;
+
+    private String type;
+
+    private String lookupName;
+
+    /**
+     * @param description The ejb-ref description.
+     * @param name The ejb-ref-name.
+     * @param type The ejb-ref-type
+     * @param lookupName The lookupname.
+     */
+    public EjbRef( String description, String name, String type, String lookupName )
+    {
+        if ( StringUtils.isEmpty( name ) )
+        {
+            throw new IllegalArgumentException( EJB_NAME + " in " + EJB_REF + " element cannot be null." );
+        }
+        else if ( StringUtils.isEmpty( type ) && StringUtils.isEmpty( lookupName ) )
+        {
+            throw new IllegalArgumentException( EJB_TYPE + " in " + EJB_REF + " element cannot be null if no "
+                + EJB_LOOKUP_NAME + " was specified." );
+
+        }
+
+        this.description = description;
+        this.name = name;
+        this.type = type;
+        this.lookupName = lookupName;
+
+    }
+
+    /**
+     * Appends the <tt>XML</tt> representation of this env-entry.
+     * 
+     * @param writer the writer to use
+     */
+    public void appendEjbRefEntry( XMLWriter writer )
+    {
+        writer.startElement( EJB_REF );
+
+        // description
+        if ( getDescription() != null )
+        {
+            doWriteElement( writer, DESCRIPTION, getDescription() );
+        }
+
+        // ejb name
+        doWriteElement( writer, EJB_NAME, getName() );
+
+        // ejb-type
+        if ( getType() != null )
+        {
+            doWriteElement( writer, EJB_TYPE, getType() );
+        }
+
+        // lookup-name
+        if ( getLookupName() != null )
+        {
+            doWriteElement( writer, EJB_LOOKUP_NAME, getLookupName() );
+        }
+
+        // end of ejb-ref
+        writer.endElement();
+    }
+
+    private void doWriteElement( XMLWriter writer, String element, String text )
+    {
+        writer.startElement( element );
+        writer.writeText( text );
+        writer.endElement();
+    }
+
+    /**
+     * @return {@link #name}
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * @param name {@link #name}
+     */
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    /**
+     * @return {@link #type}
+     */
+    public String getType()
+    {
+        return type;
+    }
+
+    /**
+     * @param type {@link #type}
+     */
+    public void setType( String type )
+    {
+        this.type = type;
+    }
+
+    /**
+     * @return {@link #lookupName}
+     */
+    public String getLookupName()
+    {
+        return lookupName;
+    }
+
+    /**
+     * @param lookupName {@link #lookupName}
+     */
+    public void setLookupName( String lookupName )
+    {
+        this.lookupName = lookupName;
+    }
+
+    /**
+     * @return {@link #description}
+     */
+    public String getDescription()
+    {
+        return description;
+    }
+}

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EnvEntry.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EnvEntry.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EnvEntry.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/EnvEntry.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,138 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.XMLWriter;
+
+/**
+ * The representation of a env-entry entry within an application.xml file.
+ * 
+ * @author Jim Brownfield based on code by <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: EnvEntry.java 1648055 2014-12-27 14:59:45Z khmarbaise $
+ */
+class EnvEntry
+{
+
+    static final String ENV_ENTRY = "env-entry";
+
+    static final String DESCRIPTION = "description";
+
+    static final String ENV_ENTRY_NAME = "env-entry-name";
+
+    static final String ENV_ENTRY_TYPE = "env-entry-type";
+
+    static final String ENV_ENTRY_VALUE = "env-entry-value";
+
+    private final String description;
+
+    private final String name;
+
+    private final String type;
+
+    private final String value;
+
+    public EnvEntry( String description, String name, String type, String value )
+    {
+        if ( StringUtils.isEmpty( name ) )
+        {
+            throw new IllegalArgumentException( ENV_ENTRY_NAME + " in " + ENV_ENTRY + " element cannot be null." );
+        }
+        else if ( StringUtils.isEmpty( type ) && StringUtils.isEmpty( value ) )
+        {
+            throw new IllegalArgumentException( ENV_ENTRY_TYPE + " in " + ENV_ENTRY + " element cannot be null if no "
+                + ENV_ENTRY_VALUE + " was specified." );
+
+        }
+
+        this.description = description;
+        this.name = name;
+        this.type = type;
+        this.value = value;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public String getType()
+    {
+        return type;
+    }
+
+    public String getValue()
+    {
+        return value;
+    }
+
+    /**
+     * Appends the <tt>XML</tt> representation of this env-entry.
+     * 
+     * @param writer the writer to use
+     */
+    public void appendEnvEntry( XMLWriter writer )
+    {
+        System.out.println( "appendEnvEntry()" );
+        writer.startElement( ENV_ENTRY );
+
+        // description
+        if ( getDescription() != null )
+        {
+            doWriteElement( writer, DESCRIPTION, getDescription() );
+        }
+
+        // env entry name
+        doWriteElement( writer, ENV_ENTRY_NAME, getName() );
+
+        // env entry type
+        if ( getType() != null )
+        {
+            doWriteElement( writer, ENV_ENTRY_TYPE, getType() );
+        }
+
+        // env entry value
+        if ( getValue() != null )
+        {
+            doWriteElement( writer, ENV_ENTRY_VALUE, getValue() );
+        }
+
+        // end of env-entry
+        writer.endElement();
+    }
+
+    private void doWriteElement( XMLWriter writer, String element, String text )
+    {
+        writer.startElement( element );
+        writer.writeText( text );
+        writer.endElement();
+    }
+
+    public String toString()
+    {
+        return "env-entry [name=" + getName() + ", type=" + getType() + ", value=" + getValue() + "]";
+    }
+
+}
\ No newline at end of file

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/GenerateApplicationXmlMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/GenerateApplicationXmlMojo.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/GenerateApplicationXmlMojo.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/GenerateApplicationXmlMojo.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,462 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+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.ear.util.JavaEEVersion;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.codehaus.plexus.interpolation.InterpolationException;
+import org.codehaus.plexus.interpolation.Interpolator;
+import org.codehaus.plexus.interpolation.MapBasedValueSource;
+import org.codehaus.plexus.interpolation.StringSearchInterpolator;
+import org.codehaus.plexus.interpolation.ValueSource;
+import org.codehaus.plexus.util.FileUtils;
+
+/**
+ * Generates the EAR deployment descriptor file(s).
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: GenerateApplicationXmlMojo.java 1713543 2015-11-09 21:32:15Z khmarbaise $
+ */
+// CHECKSTYLE_OFF: LineLength
+@Mojo( name = "generate-application-xml", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, threadSafe = true, requiresDependencyResolution = ResolutionScope.TEST )
+// CHECKSTYLE_ON: LineLength
+public class GenerateApplicationXmlMojo
+    extends AbstractEarMojo
+{
+
+    /**
+     * The DEFAULT library folder.
+     */
+    public static final String DEFAULT = "DEFAULT";
+
+    /**
+     * The empty folder.
+     */
+    public static final String EMPTY = "EMPTY";
+
+    /**
+     * The NONE not existent folder.
+     */
+    public static final String NONE = "NONE";
+
+    /**
+     * Whether the application.xml should be generated or not.
+     */
+    @Parameter( defaultValue = "true" )
+    private Boolean generateApplicationXml = Boolean.TRUE;
+
+    /**
+     * Whether a module ID should be generated if none is specified.
+     */
+    @Parameter( defaultValue = "false" )
+    private Boolean generateModuleId = Boolean.FALSE;
+
+    /**
+     * Application name of the application to be used when the application.xml file is auto-generated. Since JavaEE6.
+     */
+    @Parameter
+    private String applicationName;
+
+    /**
+     * Display name of the application to be used when the application.xml file is auto-generated.
+     */
+    @Parameter( defaultValue = "${project.artifactId}" )
+    private String displayName;
+
+    /**
+     * Description of the application to be used when the application.xml file is auto-generated.
+     */
+    @Parameter( defaultValue = "${project.description}" )
+    private String description;
+
+    /**
+     * Defines how the <tt>library-directory</tt> element should be written in the application.xml file.
+     * <p/>
+     * Three special values can be set:
+     * <ul>
+     * <li><code>DEFAULT</code> (default) generates a <tt>library-directory</tt> element with the value of the
+     * <tt>defaultLibBundleDir</tt> parameter</li>
+     * <li><code>EMPTY</code> generates an empty <tt>library-directory</tt> element. Per spec, this disables the
+     * scanning of jar files in the <tt>lib</tt> directory of the ear file</li>
+     * <li><code>NONE</code> does not write the library-directory element at all. A corner case that can be used in
+     * Oracle Weblogic to delegate the classloading to the container</li>
+     * </ul>
+     * <p/>
+     * Since JavaEE5.
+     */
+    @Parameter( defaultValue = DEFAULT )
+    private String libraryDirectoryMode;
+
+    /**
+     * Defines the value of the initialize in order element to be used when the application.xml file is auto-generated.
+     * When set to true, modules must be initialized in the order they're listed in this deployment descriptor, with the
+     * exception of application client modules, which can be initialized in any order. If initialize-in-order is not set
+     * or set to false, the order of initialization is unspecified and may be product-dependent. Since JavaEE6.
+     */
+    @Parameter
+    private Boolean initializeInOrder;
+
+    /**
+     * Defines the application id used when generating the deployment descriptor.
+     * 
+     * @since 2.9
+     */
+    @Parameter
+    private String applicationId;
+
+    /**
+     * The security-roles to be added to the auto-generated application.xml file.
+     */
+    @Parameter
+    private PlexusConfiguration security;
+
+    /**
+     * The env-entries to be added to the auto-generated application.xml file. Since JavaEE6.
+     */
+    @Parameter( alias = "env-entries" )
+    private PlexusConfiguration envEntries;
+
+    /**
+     * The {@code ejb-ref} entries.
+     */
+    @Parameter( alias = "ejb-refs" )
+    private PlexusConfiguration ejbRefs;
+
+    /**
+     * {@inheritDoc}
+     */
+    public void execute()
+        throws MojoExecutionException, MojoFailureException
+    {
+        // Initializes ear modules
+        super.execute();
+
+        // Handle application.xml
+        if ( !generateApplicationXml )
+        {
+            getLog().debug( "Generation of application.xml is disabled" );
+        }
+        else
+        {
+            final JavaEEVersion javaEEVersion = JavaEEVersion.getJavaEEVersion( version );
+
+            // Generate deployment descriptor and copy it to the build directory
+            getLog().info( "Generating application.xml" );
+            try
+            {
+                generateStandardDeploymentDescriptor( javaEEVersion );
+            }
+            catch ( EarPluginException e )
+            {
+                throw new MojoExecutionException( "Failed to generate application.xml", e );
+            }
+
+            try
+            {
+                FileUtils.copyFileToDirectory( new File( generatedDescriptorLocation, "application.xml" ),
+                                               new File( getWorkDirectory(), "META-INF" ) );
+            }
+            catch ( IOException e )
+            {
+                throw new MojoExecutionException( "Unable to copy application.xml to final destination", e );
+            }
+        }
+
+        // Handle jboss-app.xml
+        if ( getJbossConfiguration() == null )
+        {
+            getLog().debug( "Generation of jboss-app.xml is disabled" );
+        }
+        else
+        {
+            // Generate deployment descriptor and copy it to the build directory
+            getLog().info( "Generating jboss-app.xml" );
+            try
+            {
+                generateJbossDeploymentDescriptor();
+            }
+            catch ( EarPluginException e )
+            {
+                throw new MojoExecutionException( "Failed to generate jboss-app.xml", e );
+            }
+
+            try
+            {
+                FileUtils.copyFileToDirectory( new File( generatedDescriptorLocation, "jboss-app.xml" ),
+                                               new File( getWorkDirectory(), "META-INF" ) );
+            }
+            catch ( IOException e )
+            {
+                throw new MojoExecutionException( "Unable to copy jboss-app.xml to final destination", e );
+            }
+        }
+    }
+
+    /**
+     * Generates the deployment descriptor.
+     * 
+     * @param javaEEVersion {@link JavaEEVersion}
+     * @throws EarPluginException if the configuration is invalid
+     */
+    protected void generateStandardDeploymentDescriptor( JavaEEVersion javaEEVersion )
+        throws EarPluginException
+    {
+        File outputDir = new File( generatedDescriptorLocation );
+        if ( !outputDir.exists() )
+        {
+            outputDir.mkdirs();
+        }
+
+        File descriptor = new File( outputDir, "application.xml" );
+
+        final ApplicationXmlWriter writer = new ApplicationXmlWriter( javaEEVersion, encoding, generateModuleId );
+        final ApplicationXmlWriterContext context =
+            new ApplicationXmlWriterContext( descriptor, getModules(), buildSecurityRoles(), buildEnvEntries(),
+                                             buildEjbEntries(), displayName, description, getActualLibraryDirectory(),
+                                             applicationName, initializeInOrder ).setApplicationId( applicationId );
+        writer.write( context );
+    }
+
+    /**
+     * Generates the jboss deployment descriptor.
+     * 
+     * @throws EarPluginException if the configuration is invalid
+     */
+    protected void generateJbossDeploymentDescriptor()
+        throws EarPluginException
+    {
+        File outputDir = new File( generatedDescriptorLocation );
+        if ( !outputDir.exists() )
+        {
+            outputDir.mkdirs();
+        }
+
+        File descriptor = new File( outputDir, "jboss-app.xml" );
+
+        JbossAppXmlWriter writer = new JbossAppXmlWriter( encoding );
+        writer.write( descriptor, getJbossConfiguration(), getModules() );
+    }
+
+    /**
+     * Builds the security roles based on the configuration.
+     * 
+     * @return a list of SecurityRole object(s)
+     * @throws EarPluginException if the configuration is invalid
+     */
+    private List<SecurityRole> buildSecurityRoles()
+        throws EarPluginException
+    {
+        final List<SecurityRole> result = new ArrayList<SecurityRole>();
+        if ( security == null )
+        {
+            return result;
+        }
+        final PlexusConfiguration[] securityRoles = security.getChildren( SecurityRole.SECURITY_ROLE );
+
+        for ( PlexusConfiguration securityRole : securityRoles )
+        {
+            final String id = securityRole.getAttribute( SecurityRole.ID_ATTRIBUTE );
+            final String childRoleName = securityRole.getChild( SecurityRole.ROLE_NAME ).getValue();
+            final String childRoleNameId =
+                securityRole.getChild( SecurityRole.ROLE_NAME ).getAttribute( SecurityRole.ID_ATTRIBUTE );
+            final String childDescription = securityRole.getChild( SecurityRole.DESCRIPTION ).getValue();
+            final String childDescriptionId =
+                securityRole.getChild( SecurityRole.DESCRIPTION ).getAttribute( SecurityRole.ID_ATTRIBUTE );
+
+            if ( childRoleName == null )
+            {
+                throw new EarPluginException( "Invalid security-role configuration, role-name could not be null." );
+            }
+            else
+            {
+                result.add( new SecurityRole( childRoleName, childRoleNameId, id, childDescription,
+                                              childDescriptionId ) );
+            }
+        }
+        return result;
+    }
+
+    /**
+     * This help method was needed otherwise the interpolate method of interpolator will make an empty string of a
+     * {@code null} element which results in supplemental elements for env-entry.
+     * 
+     * @param interpolator The interpolator
+     * @param element The element
+     * @return The interpolated elements.
+     * @throws InterpolationException in case of an error.
+     */
+    private String interpolate( Interpolator interpolator, String element )
+        throws InterpolationException
+    {
+        if ( element == null )
+        {
+            return element;
+        }
+        else
+        {
+            return interpolator.interpolate( element );
+        }
+    }
+
+    /**
+     * Builds the env-entries based on the configuration.
+     * 
+     * @return a list of EnvEntry object(s)
+     * @throws EarPluginException if the configuration is invalid
+     */
+    private List<EnvEntry> buildEnvEntries()
+        throws EarPluginException
+    {
+        final List<EnvEntry> result = new ArrayList<EnvEntry>();
+        if ( envEntries == null )
+        {
+            return result;
+        }
+        try
+        {
+            StringSearchInterpolator ssi = new StringSearchInterpolator();
+            ValueSource vs = new MapBasedValueSource( project.getProperties() );
+            ssi.addValueSource( vs );
+
+            final PlexusConfiguration[] allEnvEntries = envEntries.getChildren( EnvEntry.ENV_ENTRY );
+
+            for ( PlexusConfiguration envEntry : allEnvEntries )
+            {
+                // CHECKSTYLE_OFF: LineLength
+                final String childDescription =
+                    interpolate( ssi, envEntry.getChild( EnvEntry.DESCRIPTION ).getValue() );
+                final String childEnvEntryName =
+                    interpolate( ssi, envEntry.getChild( EnvEntry.ENV_ENTRY_NAME ).getValue() );
+                final String childEnvEntryType =
+                    interpolate( ssi, envEntry.getChild( EnvEntry.ENV_ENTRY_TYPE ).getValue() );
+                final String childEnvEntryValue =
+                    interpolate( ssi, envEntry.getChild( EnvEntry.ENV_ENTRY_VALUE ).getValue() );
+                // CHECKSTYLE_ON: LineLength
+
+                try
+                {
+                    result.add( new EnvEntry( childDescription, childEnvEntryName, childEnvEntryType,
+                                              childEnvEntryValue ) );
+                }
+                catch ( IllegalArgumentException e )
+                {
+                    throw new EarPluginException( "Invalid env-entry [" + envEntry + "]", e );
+                }
+            }
+            return result;
+        }
+        catch ( InterpolationException e )
+        {
+            throw new EarPluginException( "Interpolation exception:", e );
+        }
+
+    }
+
+    /**
+     * Builds the ejb-ref based on the configuration.
+     * 
+     * @return a list of EjbRef object(s)
+     * @throws EarPluginException if the configuration is invalid
+     */
+    private List<EjbRef> buildEjbEntries()
+        throws EarPluginException
+    {
+        final List<EjbRef> result = new ArrayList<EjbRef>();
+        if ( ejbRefs == null )
+        {
+            return result;
+        }
+        try
+        {
+            StringSearchInterpolator ssi = new StringSearchInterpolator();
+            ValueSource vs = new MapBasedValueSource( project.getProperties() );
+            ssi.addValueSource( vs );
+
+            final PlexusConfiguration[] allEjbEntries = ejbRefs.getChildren( EjbRef.EJB_REF );
+
+            for ( PlexusConfiguration ejbEntry : allEjbEntries )
+            {
+                // CHECKSTYLE_OFF: LineLength
+                final String childDescription =
+                    interpolate( ssi, ejbEntry.getChild( EnvEntry.DESCRIPTION ).getValue() );
+                final String childEjbEntryName = interpolate( ssi, ejbEntry.getChild( EjbRef.EJB_NAME ).getValue() );
+                final String childEjbEntryType = interpolate( ssi, ejbEntry.getChild( EjbRef.EJB_TYPE ).getValue() );
+                final String childEjbLookupNameValue =
+                    interpolate( ssi, ejbEntry.getChild( EjbRef.EJB_LOOKUP_NAME ).getValue() );
+                // CHECKSTYLE_ON: LineLength
+
+                try
+                {
+                    result.add( new EjbRef( childDescription, childEjbEntryName, childEjbEntryType,
+                                            childEjbLookupNameValue ) );
+                }
+                catch ( IllegalArgumentException e )
+                {
+                    throw new EarPluginException( "Invalid ejb-ref [" + ejbEntry + "]", e );
+                }
+            }
+            return result;
+        }
+        catch ( InterpolationException e )
+        {
+            throw new EarPluginException( "Interpolation exception:", e );
+        }
+
+    }
+
+    /**
+     * Returns the value to use for the <tt>library-directory</tt> element, based on the library directory mode.
+     */
+    private String getActualLibraryDirectory()
+        throws EarPluginException
+    {
+        final String mode = libraryDirectoryMode == null ? DEFAULT : libraryDirectoryMode.toUpperCase();
+
+        if ( DEFAULT.equals( mode ) )
+        {
+            return defaultLibBundleDir;
+        }
+        else if ( EMPTY.equals( mode ) )
+        {
+            return "";
+        }
+        else if ( NONE.equals( mode ) )
+        {
+            return null;
+        }
+        else
+        {
+            throw new EarPluginException( "Unsupported library directory mode [" + libraryDirectoryMode
+                + "] Supported modes " + ( Arrays.asList( DEFAULT, EMPTY, NONE ) ) );
+        }
+    }
+}
\ No newline at end of file

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/HarModule.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/HarModule.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/HarModule.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/HarModule.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,79 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.codehaus.plexus.util.xml.XMLWriter;
+
+/**
+ * The {@link EarModule} implementation for a JBoss Hibernate archive.
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: HarModule.java 1645331 2014-12-13 17:31:09Z khmarbaise $
+ */
+public class HarModule
+    extends AbstractEarModule
+    implements JbossEarModule
+{
+    /**
+     * Create an instance.
+     */
+    public HarModule()
+    {
+    }
+
+    /**
+     * @param a {@link Artifact}
+     */
+    public HarModule( Artifact a )
+    {
+        super( a );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void appendModule( XMLWriter writer, String version, Boolean generateId )
+    {
+        // No entry is generated by this artifact ; it should be
+        // defined in the jboss-app.xml.
+        // See http://docs.jboss.org/jbossas/getting_started/v4/html/hibernate.html
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void appendJbossModule( XMLWriter writer, String version )
+    {
+        writer.startElement( MODULE_ELEMENT );
+        writer.startElement( "har" );
+        writer.writeText( getUri() );
+        writer.endElement();
+        writer.endElement();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getType()
+    {
+        return "har";
+    }
+}

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JarModule.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JarModule.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JarModule.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JarModule.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,123 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+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 non J2EE module such as third party libraries.
+ * <p/>
+ * Such module is not incorporated in the generated <tt>application.xml<tt>
+ * but some application servers support it. To include it in the generated
+ * deployment descriptor anyway, set the <tt>includeInApplicationXml</tt> boolean flag.
+ * <p/>
+ * This class deprecates {@link org.apache.maven.plugins.ear.JavaModule}.
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: JarModule.java 1648046 2014-12-27 11:07:02Z khmarbaise $
+ */
+public class JarModule
+    extends AbstractEarModule
+{
+    private Boolean includeInApplicationXml = Boolean.FALSE;
+
+    /**
+     * Create an instance.
+     */
+    public JarModule()
+    {
+        super();
+    }
+
+    /**
+     * @param a {@link Artifact}
+     * @param defaultLibBundleDir The default library bundle directory.
+     * @param includeInApplicationXml Include the application xml or not.
+     */
+    public JarModule( Artifact a, String defaultLibBundleDir, Boolean includeInApplicationXml )
+    {
+        super( a );
+        setLibBundleDir( defaultLibBundleDir );
+        this.includeInApplicationXml = includeInApplicationXml;
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void appendModule( XMLWriter writer, String version, Boolean generateId )
+    {
+        // Generates an entry in the application.xml only if
+        // includeInApplicationXml is set
+        if ( includeInApplicationXml )
+        {
+            startModuleElement( writer, generateId );
+            writer.startElement( JAVA_MODULE );
+            writer.writeText( getUri() );
+            writer.endElement();
+
+            writeAltDeploymentDescriptor( writer, version );
+
+            writer.endElement();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void resolveArtifact( Set<Artifact> 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() );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getType()
+    {
+        return "jar";
+    }
+
+    private void setLibBundleDir( String defaultLibBundleDir )
+    {
+        if ( defaultLibBundleDir != null && bundleDir == null )
+        {
+            this.bundleDir = defaultLibBundleDir;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean changeManifestClasspath()
+    {
+        return false;
+    }
+}

Added: maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JbossAppXmlWriter.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JbossAppXmlWriter.java?rev=1755643&view=auto
==============================================================================
--- maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JbossAppXmlWriter.java (added)
+++ maven/plugins/trunk/maven-ear-plugin/src/main/java/org/apache/maven/plugins/ear/JbossAppXmlWriter.java Tue Aug  9 19:17:58 2016
@@ -0,0 +1,191 @@
+package org.apache.maven.plugins.ear;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.Writer;
+import java.util.List;
+
+import org.codehaus.plexus.util.xml.XMLWriter;
+
+/**
+ * An <tt>XmlWriter</tt> based implementation used to generate a <tt>jboss-app.xml</tt> file
+ * 
+ * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
+ * @version $Id: JbossAppXmlWriter.java 1636449 2014-11-03 21:27:36Z khmarbaise $
+ */
+final class JbossAppXmlWriter
+    extends AbstractXmlWriter
+{
+
+    public static final String DOCTYPE_3_2 = "jboss-app PUBLIC\n" + "\t\"-//JBoss//DTD J2EE Application 1.3//EN\"\n"
+        + "\t\"http://www.jboss.org/j2ee/dtd/jboss-app_3_2.dtd\"";
+
+    public static final String DOCTYPE_4 = "jboss-app PUBLIC\n" + "\t\"-//JBoss//DTD J2EE Application 1.4//EN\"\n"
+        + "\t\"http://www.jboss.org/j2ee/dtd/jboss-app_4_0.dtd\"";
+
+    public static final String DOCTYPE_4_2 = "jboss-app PUBLIC\n" + "\t\"-//JBoss//DTD J2EE Application 4.2//EN\"\n"
+        + "\t\"http://www.jboss.org/j2ee/dtd/jboss-app_4_2.dtd\"";
+
+    public static final String DOCTYPE_5 = "jboss-app PUBLIC\n" + "\t\"-//JBoss//DTD Java EE Application 5.0//EN\"\n"
+        + "\t\"http://www.jboss.org/j2ee/dtd/jboss-app_5_0.dtd\"";
+
+    private static final String JBOSS_APP_ELEMENT = "jboss-app";
+
+    JbossAppXmlWriter( String encoding )
+    {
+        super( encoding );
+    }
+
+    public void write( File destinationFile, JbossConfiguration jbossConfiguration, List<EarModule> earModules )
+        throws EarPluginException
+    {
+        final Writer w = initializeWriter( destinationFile );
+
+        XMLWriter writer;
+        if ( jbossConfiguration.isJbossThreeDotTwo() )
+        {
+            writer = initializeXmlWriter( w, DOCTYPE_3_2 );
+        }
+        else if ( jbossConfiguration.isJbossFour() )
+        {
+            writer = initializeXmlWriter( w, DOCTYPE_4 );
+        }
+        else if ( jbossConfiguration.isJbossFourDotTwo() )
+        {
+            writer = initializeXmlWriter( w, DOCTYPE_4_2 );
+        }
+        else
+        {
+            writer = initializeXmlWriter( w, DOCTYPE_5 );
+        }
+        writer.startElement( JBOSS_APP_ELEMENT );
+
+        // Make sure to write the things in the right order so that the DTD validates
+
+        // module-order (only available as from 4.2)
+        if ( jbossConfiguration.isJbossFourDotTwoOrHigher() && jbossConfiguration.getModuleOrder() != null )
+        {
+            writer.startElement( JbossConfiguration.MODULE_ORDER );
+            writer.writeText( jbossConfiguration.getModuleOrder() );
+            writer.endElement();
+        }
+
+        // If JBoss 4, write the jboss4 specific stuff
+        if ( jbossConfiguration.isJbossFourOrHigher() )
+        {
+            if ( jbossConfiguration.getSecurityDomain() != null )
+            {
+                writer.startElement( JbossConfiguration.SECURITY_DOMAIN );
+                writer.writeText( jbossConfiguration.getSecurityDomain() );
+                writer.endElement();
+            }
+            if ( jbossConfiguration.getUnauthenticatedPrincipal() != null )
+            {
+                writer.startElement( JbossConfiguration.UNAUHTHENTICTED_PRINCIPAL );
+                writer.writeText( jbossConfiguration.getUnauthenticatedPrincipal() );
+                writer.endElement();
+            }
+        }
+
+        // classloader repository
+        // CHECKSTYLE_OFF: LineLength
+        if ( jbossConfiguration.getLoaderRepository() != null || jbossConfiguration.getLoaderRepositoryConfig() != null )
+        // CHECKSTYLE_ON: LineLength
+        {
+            writer.startElement( JbossConfiguration.LOADER_REPOSITORY );
+
+            // classloader repository class
+            if ( jbossConfiguration.getLoaderRepositoryClass() != null )
+            {
+                writer.addAttribute( JbossConfiguration.LOADER_REPOSITORY_CLASS_ATTRIBUTE,
+                                     jbossConfiguration.getLoaderRepositoryClass() );
+            }
+
+            // we don't need to write any text if only the loader repo configuration is changed
+            if ( jbossConfiguration.getLoaderRepository() != null )
+            {
+                writer.writeText( jbossConfiguration.getLoaderRepository() );
+            }
+
+            // classloader configuration
+            if ( jbossConfiguration.getLoaderRepositoryConfig() != null )
+            {
+                writer.startElement( JbossConfiguration.LOADER_REPOSITORY_CONFIG );
+
+                // classloader configuration parser
+                if ( jbossConfiguration.getConfigParserClass() != null )
+                {
+                    writer.addAttribute( JbossConfiguration.CONFIG_PARSER_CLASS_ATTRIBUTE,
+                                         jbossConfiguration.getConfigParserClass() );
+                }
+                writer.writeText( jbossConfiguration.getLoaderRepositoryConfig() );
+                writer.endElement();
+            }
+
+            writer.endElement();
+        }
+
+        // jmx name
+        if ( jbossConfiguration.getJmxName() != null )
+        {
+            writer.startElement( JbossConfiguration.JMX_NAME );
+            writer.writeText( jbossConfiguration.getJmxName() );
+            writer.endElement();
+        }
+
+        // library-directory (only available as from 4.2)
+        if ( jbossConfiguration.isJbossFourDotTwoOrHigher() && jbossConfiguration.getLibraryDirectory() != null )
+        {
+            writer.startElement( JbossConfiguration.LIBRARY_DIRECTORY );
+            writer.writeText( jbossConfiguration.getLibraryDirectory() );
+            writer.endElement();
+        }
+
+        // Modules
+
+        List<String> dataSources = jbossConfiguration.getDataSources();
+        // Write out data source modules first
+        if ( dataSources != null )
+        {
+            for ( String dsPath : dataSources )
+            {
+                writer.startElement( MODULE_ELEMENT );
+                writer.startElement( SERVICE_ELEMENT );
+                writer.writeText( dsPath );
+                writer.endElement();
+                writer.endElement();
+            }
+        }
+
+        // Write the JBoss specific modules
+        for ( EarModule earModule : earModules )
+        {
+            if ( JbossEarModule.class.isInstance( earModule ) )
+            {
+                JbossEarModule jbossEarModule = (JbossEarModule) earModule;
+                jbossEarModule.appendJbossModule( writer, jbossConfiguration.getVersion() );
+            }
+        }
+        writer.endElement();
+
+        close( w );
+    }
+}
\ No newline at end of file



Mime
View raw message