Index: /home/jh/Sources/codehaus/rpm-maven-plugin/src/main/java/org/codehaus/mojo/rpm/RPMMojo.java
===================================================================
--- /home/jh/Sources/codehaus/rpm-maven-plugin/src/main/java/org/codehaus/mojo/rpm/RPMMojo.java	(revision 5637)
+++ /home/jh/Sources/codehaus/rpm-maven-plugin/src/main/java/org/codehaus/mojo/rpm/RPMMojo.java	(working copy)
@@ -51,211 +51,211 @@
  */
 public class RPMMojo extends AbstractMojo
 {
-    
+
     /**
      * The name portion of the output file name.
      * @parameter expression="${project.artifactId}"
      * @required
      */
     private String name;
-    
+
     /**
      * The version portion of the RPM file name.
      * @parameter alias="version" expression="${project.version}"
      * @required
      */
     private String projversion;
-    
+
     /**
      * The release portion of the RPM file name.
      * @parameter
      * @required
      */
     private String release;
-    
+
     /**
      * Set to <code>true</code> if the package is dependent on the architecture
      * of the build machine.
      * @parameter
      */
     private boolean needarch;
-    
+
     /**
      * The long description of the package.
      * @parameter expression="${project.description}"
      */
     private String description;
-    
+
     /**
      * The one-line description of the package.
      * @parameter expression="${project.name}"
      */
     private String summary;
-    
+
     /**
      * The one-line copyright information.
      * @parameter
      */
     private String copyright;
-    
+
     /**
      * The distribution containing this package.
      * @parameter
      */
     private String distribution;
-    
+
     /**
      * An icon for the package.
      * @parameter
      */
     private File icon;
-    
+
     /**
      * The vendor supplying the package.
      * @parameter expression="${project.organization.name}"
      */
     private String vendor;
-    
+
     /**
      * A URL for the vendor.
      * @parameter expression="${project.organization.url}"
      */
     private String url;
-    
+
     /**
      * The package group for the package.
      * @parameter
      * @required
      */
     private String group;
-    
+
     /**
      * The name of the person or group creating the package.
      * @parameter expression="${project.organization.name}"
      */
     private String packager;
-    
+
     /**
      * The list of virtual packages provided by this package.
      * @parameter
      */
     private List provides;
-    
+
     /**
      * The list of requirements for this package.
      * @parameter
      */
     private List requires;
-    
+
     /**
      * The list of conflicts for this package.
      * @parameter
      */
     private List conflicts;
-    
+
     /**
      * The relocation prefix for this package.
      * @parameter
      */
     private String prefix;
-    
+
     /**
      * The area for RPM to use for building the package.
      * @parameter expression="${project.build.directory}/rpm"
      */
     private File workarea;
-    
+
     /**
      * The list of file mappings.
      * @parameter
      * @required
      */
     private List mappings;
-    
+
     /**
      * The pre-installation script.
      * @parameter
      */
     private String preinstall;
-    
+
     /**
      * The location of the pre-installation script.
      * @parameter
      */
     private File preinstallScript;
-    
+
     /**
      * The post-installation script.
      * @parameter
      */
     private String postinstall;
-    
+
     /**
      * The location of the post-installation script.
      * @parameter
      */
     private File postinstallScript;
-    
+
     /**
      * The installation script.
      * @parameter
      */
     private String install;
-    
+
     /**
      * The location of the installation script.
      * @parameter
      */
     private File installScript;
-    
+
     /**
      * The pre-removal script.
      * @parameter
      */
     private String preremove;
-    
+
     /**
      * The location of the pre-removal script.
      * @parameter
      */
     private File preremoveScript;
-    
+
     /**
      * The post-removal script.
      * @parameter
      */
     private String postremove;
-    
+
     /**
      * The location of the post-removal script.
      * @parameter
      */
     private File postremoveScript;
-    
+
     /**
      * The verification script.
      * @parameter
      */
     private String verify;
-    
+
     /**
      * The location of the verification script.
      * @parameter
      */
     private File verifyScript;
-    
+
     /**
      * The clean script.
      * @parameter
      */
     private String clean;
-    
+
     /**
      * The location of the clean script.
      * @parameter
      */
     private File cleanScript;
-    
+
     /**
      * A Plexus component to copy files and directories.
      * @component role="org.codehaus.plexus.archiver.Archiver"
@@ -278,29 +278,29 @@
      * @readonly
      */
     private List attachedArtifacts;
-    
+
     /**
      * @parameter default-value="${project}"
      * @required
      * @readonly
      */
     private MavenProject project;
-    
+
     /**
      * A list of %define arguments
      * @parameter
      */
     private List defineStatements;
-    
-    
+
+
     /** The root of the build area. */
     private File buildroot;
-    
+
     /** The version string after parsing. */
     private String version;
-    
+
     // // //  Consumers for rpmbuild output
-    
+
     /**
      * Consumer to receive lines sent to stdout.  The lines are logged
      * as info.
@@ -309,7 +309,7 @@
     {
         /** Logger to receive the lines. */
         private Log logger;
-        
+
         /**
          * Constructor.
          * @param log The logger to receive the lines
@@ -318,7 +318,7 @@
         {
             logger = log;
         }
-        
+
         /**
          * Consume a line.
          * @param string The line to consume
@@ -328,7 +328,7 @@
             logger.info( string );
         }
     }
-    
+
     /**
      * Consumer to receive lines sent to stderr.  The lines are logged
      * as warnings.
@@ -337,7 +337,7 @@
     {
         /** Logger to receive the lines. */
         private Log logger;
-        
+
         /**
          * Constructor.
          * @param log The logger to receive the lines
@@ -346,7 +346,7 @@
         {
             logger = log;
         }
-        
+
         /**
          * Consume a line.
          * @param string The line to consume
@@ -356,9 +356,9 @@
             logger.warn( string );
         }
     }
-    
+
     // // //  Mojo methods
-    
+
     /** {@inheritDoc} */
     public void execute() throws MojoExecutionException, MojoFailureException
     {
@@ -368,9 +368,9 @@
         installFiles();
         buildPackage();
     }
-    
+
     // // //  Internal methods
-    
+
     /**
      * Run the external command to build the package.
      * @throws MojoExecutionException if an error occurs
@@ -378,7 +378,7 @@
     private void buildPackage() throws MojoExecutionException
     {
         File f = new File( workarea, "SPECS" );
-        
+
         Commandline cl = new Commandline();
         cl.setExecutable( "rpmbuild" );
         cl.setWorkingDirectory( f.getAbsolutePath() );
@@ -391,7 +391,7 @@
             cl.createArgument().setValue( "noarch" );
         }
         cl.createArgument().setValue( name + ".spec" );
-        
+
         StreamConsumer stdout = new StdoutConsumer( getLog() );
         StreamConsumer stderr = new StderrConsumer( getLog() );
         try
@@ -407,7 +407,7 @@
             throw new MojoExecutionException( "Unable to build the RPM", e );
         }
     }
-    
+
     /**
      * Build the structure of the work area.
      * @throws MojoFailureException if a directory cannot be built
@@ -415,7 +415,7 @@
     private void buildWorkArea() throws MojoFailureException
     {
         final String[] topdirs = { "BUILD", "RPMS", "SOURCES", "SPECS", "SRPMS" };
-        
+
         // Build the top directory
         if ( !workarea.exists() )
         {
@@ -425,7 +425,7 @@
                 throw new MojoFailureException( "Unable to create directory " + workarea.getAbsolutePath() );
             }
         }
-        
+
         // Build each directory in the top directory
         for ( int i = 0; i < topdirs.length; i++ )
         {
@@ -439,7 +439,7 @@
                 }
             }
         }
-        
+
         // Build the build root
         buildroot = new File( workarea, "buildroot" );
         if ( !buildroot.exists() )
@@ -451,7 +451,7 @@
             }
         }
     }
-    
+
     /**
      * Check the parameters for validity.
      * @throws MojoFailureException if an invalid parameter is found
@@ -469,7 +469,7 @@
             version = projversion.substring( 0, projversion.indexOf( "-" ) );
             getLog().warn( "Version string truncated to " + version );
         }
-        
+
         // Various checks in the mappings
         for ( Iterator it = mappings.iterator(); it.hasNext(); )
         {
@@ -490,7 +490,7 @@
                 }
             }
         }
-        
+
         // Collect the scripts, if necessary
         if ( ( preinstall == null ) && ( preinstallScript != null ) )
         {
@@ -521,7 +521,7 @@
             clean = readFile( cleanScript );
         }
     }
-    
+
     /**
      * Copy an artifact.
      * @param art The artifact to copy
@@ -538,7 +538,7 @@
         }
         copySource( art.getFile(), dest, null, null );
     }
-    
+
     /**
      * Copy a set of files.
      * @param src The file or directory to start copying from
@@ -562,13 +562,13 @@
                 {
                     ia = (String[]) incl.toArray( new String[0] );
                 }
-                
+
                 String[] ea = null;
                 if ( excl != null )
                 {
                     ea = (String[]) excl.toArray( new String[0] );
                 }
-                
+
                 copier.addDirectory( src, "", ia, ea );
             }
             else
@@ -587,7 +587,7 @@
             throw new MojoExecutionException( "Unable to copy files for packaging: " + t.getMessage(), t );
         }
     }
-    
+
     /**
      * Determine if the dependency matches an include or exclude list.
      * @param dep The dependency to check
@@ -601,7 +601,7 @@
             // No list, not possible to match
             return false;
         }
-        
+
         for ( Iterator it = list.iterator(); it.hasNext(); )
         {
             Artifact item = (Artifact) it.next();
@@ -628,11 +628,11 @@
                 }
             }
         }
-        
+
         // Not found
         return false;
     }
-    
+
     /**
      * Copy the files from the various mapping sources into the build root.
      * @throws MojoExecutionException if a problem occurs
@@ -645,13 +645,13 @@
             File icondest = new File( workarea, "SOURCES" );
             copySource( icon, icondest, null, null );
         }
-        
+
         // Process each mapping
         for ( Iterator it = mappings.iterator(); it.hasNext(); )
         {
             Mapping map = (Mapping) it.next();
             File dest = new File( buildroot + map.getDestination() );
-            
+
             if ( map.isDirOnly() )
             {
                 // Build the output directory if it doesn't exist
@@ -664,6 +664,14 @@
                     }
                 }
             }
+            else if (map.getSourceFile() != null)
+            {
+                if (!map.getSourceFile().isFile())
+                {
+                    throw new MojoExecutionException("SourceFile is not a plain file " + map.getSourceFile().getAbsolutePath());
+                }
+                copySource( map.getSourceFile(), dest, null, null );
+            }
             else
             {
                 List srcs = map.getSources();
@@ -692,7 +700,7 @@
                         }
                     }
                 }
-                
+
                 ArtifactMap art = map.getArtifact();
                 if ( art != null )
                 {
@@ -702,7 +710,7 @@
                         copyArtifact( (Artifact) ait.next(), dest );
                     }
                 }
-                
+
                 Dependency dep = map.getDependency();
                 if ( dep != null )
                 {
@@ -715,7 +723,7 @@
             }
         }
     }
-    
+
     /**
      * Read a file into a string.
      * @param in The file to read
@@ -741,7 +749,7 @@
             throw new MojoExecutionException( "Unable to read " + in.getAbsolutePath(), t );
         }
     }
-    
+
     /**
      * Make a list of the artifacts to package in this mapping.
      * @param am The artifact mapping information
@@ -751,7 +759,7 @@
     {
         List retval = new ArrayList();
         List clist = am.getClassifiers();
-        
+
         if ( clist == null )
         {
             retval.add( artifact );
@@ -772,10 +780,10 @@
                 }
             }
         }
-        
+
         return retval;
     }
-    
+
     /**
      * Make a list of the dependencies to package in this mapping.
      * @param d The artifact mapping information
@@ -807,10 +815,10 @@
                 }
             }
         }
-        
+
         return retval;
     }
-    
+
     /**
      * Write the SPEC file.
      * @throws MojoExecutionException if an error occurs writing the file
@@ -823,14 +831,14 @@
         {
             getLog().info( "Creating spec file " + specf.getAbsolutePath() );
             PrintWriter spec = new PrintWriter( new FileWriter( specf ) );
-            
+
             if ( null != defineStatements )
             {
                 Iterator defineIter = defineStatements.iterator();
                 String defineStatement = (String) defineIter.next();
                 spec.println( "%define " + defineStatement );
             }
-            
+
             spec.println( "Name: " + name );
             spec.println( "Version: " + version );
             spec.println( "Release: " + release );
@@ -898,15 +906,22 @@
             {
                 spec.println( description );
             }
-            
+
             spec.println();
             spec.println( "%files" );
             for ( Iterator it = mappings.iterator(); it.hasNext(); )
             {
                 Mapping map = (Mapping) it.next();
-                spec.println( map.getAttrString() + " " + map.getDestination() );
+                if (map.getSourceFile() != null)
+                {
+                    spec.println( map.getAttrString() + " " + map.getDestination() + File.separator + map.getSourceFile().getName());
+                }
+                else
+                {
+                    spec.println( map.getAttrString() + " " + map.getDestination() );
+                }
             }
-            
+
             if ( preinstall != null )
             {
                 spec.println();
@@ -949,7 +964,7 @@
                 spec.println( "%clean" );
                 spec.println( clean );
             }
-            
+
             spec.close();
         }
         catch ( Throwable t )
Index: /home/jh/Sources/codehaus/rpm-maven-plugin/src/main/java/org/codehaus/mojo/rpm/Mapping.java
===================================================================
--- /home/jh/Sources/codehaus/rpm-maven-plugin/src/main/java/org/codehaus/mojo/rpm/Mapping.java	(revision 5637)
+++ /home/jh/Sources/codehaus/rpm-maven-plugin/src/main/java/org/codehaus/mojo/rpm/Mapping.java	(working copy)
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+import java.io.File;
 import java.util.List;
 
 /**
@@ -29,38 +30,41 @@
  */
 public class Mapping
 {
-    
+
     // // //  Properties
-    
+
     /** Destination directory name. */
     private String directory;
-    
+
     /** <code>true</code> if the files are configuration. */
     private boolean configuration;
-    
+
     /** <code>true</code> if the files are documentation. */
     private boolean documentation;
-    
+
     /** File mode (octal string) to assign to files when installed. */
     private String filemode;
-    
+
     /** User name for files when installed. */
     private String username;
-    
+
     /** Group name for files when installed. */
     private String groupname;
-    
+
     /** Mapping information for source directories. */
     private List sources;
-    
+
+    /** Single file mapping. Mutually exclusive with sources. */
+    private File sourceFile;
+
     /** Mapping information for artifacts. */
     private ArtifactMap artifact;
-    
+
     /** Mapping information for dependencies. */
     private Dependency dependency;
-    
+
     // // //  Bean methods
-    
+
     /**
      * Retrieve the destination during package installation.
      * @return The destination during package installation.
@@ -69,7 +73,7 @@
     {
         return directory;
     }
-    
+
     /**
      * Set the destination during package installation.
      * @param dir The new destination during package installation.
@@ -78,7 +82,7 @@
     {
         directory = dir;
     }
-    
+
     /**
      * Retrieve the configuration status.  This value is <code>true</code> if
      * the file(s) in this mapping are configuration files.
@@ -88,7 +92,7 @@
     {
         return configuration;
     }
-    
+
     /**
      * Set the configuration status.  This value is <code>true</code> if
      * the file(s) in this mapping are configuration files.
@@ -98,7 +102,7 @@
     {
         configuration = isCfg;
     }
-    
+
     /**
      * Retrieve the documentation status.  This value is <code>true</code> if
      * the file(s) in this mapping are documentation files.
@@ -108,7 +112,7 @@
     {
         return documentation;
     }
-    
+
     /**
      * Set the documentation status.  This value is <code>true</code> if
      * the file(s) in this mapping are documentation files.
@@ -118,7 +122,7 @@
     {
         documentation = isDoc;
     }
-    
+
     /**
      * Retrieve the UNIX file permissions.  This is a three-digit octal number
      * which specifies the permissions to be applied to each file in the
@@ -129,7 +133,7 @@
     {
         return filemode;
     }
-    
+
     /**
      * Set the UNIX file permissions.  This is a three-digit octal number
      * which specifies the permissions to be applied to each file in the
@@ -140,7 +144,7 @@
     {
         filemode = fmode;
     }
-    
+
     /**
      * Retrieve the UNIX user name to own the installed files.  Note that this
      * must be a name, not a numeric user ID.
@@ -150,7 +154,7 @@
     {
         return username;
     }
-    
+
     /**
      * Set the UNIX user name to own the installed files.  Note that this
      * must be a name, not a numeric user ID.
@@ -160,7 +164,7 @@
     {
         username = uname;
     }
-    
+
     /**
      * Retrieve the UNIX group name to own the installed files.  Note that this
      * must be a name, not a numeric group ID.
@@ -170,7 +174,7 @@
     {
         return groupname;
     }
-    
+
     /**
      * Set the UNIX group name to own the installed files.  Note that this
      * must be a name, not a numeric group ID.
@@ -180,7 +184,7 @@
     {
         groupname = grpname;
     }
-    
+
     /**
      * Retrieve the list of source file specifications.
      * @return The list of source file specifications.
@@ -189,7 +193,7 @@
     {
         return sources;
     }
-    
+
     /**
      * Set the list of source file specifications.
      * @param srclist The new list of source file specifications.
@@ -198,8 +202,26 @@
     {
         sources = srclist;
     }
-    
+
     /**
+     * Retrieve the sourceFile.
+     * @return the single sourceFile.
+     */
+    public File getSourceFile()
+    {
+        return sourceFile;
+    }
+
+    /**
+     * Set the source file.
+     * @param sourceFile a single file specification.
+     */
+    public void setSourceFile(File sourceFile)
+    {
+        this.sourceFile = sourceFile;
+    }
+
+    /**
      * Retrieve the artifact specification.
      * @return The artifact specification.
      */
@@ -207,7 +229,7 @@
     {
         return artifact;
     }
-    
+
     /**
      * Set the artifact specification.
      * @param am The new artifact specification.
@@ -216,7 +238,7 @@
     {
         artifact = am;
     }
-    
+
     /**
      * Retrieve the dependency specification.
      * @return The dependency specification.
@@ -225,7 +247,7 @@
     {
         return dependency;
     }
-    
+
     /**
      * Set the dependency specification.
      * @param am The new dependency specification.
@@ -234,9 +256,9 @@
     {
         dependency = am;
     }
-    
+
     // // //  Public methods
-    
+
     /**
      * Assemble the RPM SPEC file attributes for a mapping.
      * @return The attribute string for the SPEC file.
@@ -244,23 +266,23 @@
     public String getAttrString()
     {
         StringBuffer sb = new StringBuffer();
-        
+
         if ( configuration )
         {
             sb.append( "%config " );
         }
-        
+
         if ( documentation )
         {
             sb.append( "%doc " );
         }
-        
+
         if ( ( ( sources == null ) || ( sources.size() == 0 ) )
                 && ( dependency == null ) && ( artifact == null ) )
         {
             sb.append( "%dir " );
         }
-        
+
         if ( filemode != null )
         {
             sb.append( "%attr(" + filemode + "," );
@@ -269,7 +291,7 @@
         {
             sb.append( "%attr(-," );
         }
-        
+
         if ( username != null )
         {
             sb.append( username + "," );
@@ -278,7 +300,7 @@
         {
             sb.append( "-," );
         }
-        
+
         if ( groupname != null )
         {
             sb.append( groupname + ")" );
@@ -287,10 +309,10 @@
         {
             sb.append( "-)" );
         }
-        
+
         return sb.toString();
     }
-    
+
     /**
      * Return the destination directory name.
      * @return The name of the destination directory.
@@ -306,40 +328,45 @@
             return directory;
         }
     }
-    
+
     /**
      * Return directory-only status.
      * @return <code>true</code> if no sources were specified in the mapping
      */
     public boolean isDirOnly()
     {
+        if (sourceFile != null)
+        {
+            return false;
+        }
+
         if ( ( sources != null ) && ( !sources.isEmpty() ) )
         {
             return false;
         }
-        
+
         if ( artifact != null )
         {
             return false;
         }
-        
+
         if ( dependency != null )
         {
             return false;
         }
-        
+
         return true;
     }
-    
+
     /** {@inheritDoc} */
     public String toString()
     {
         boolean sourceShown = false;
         StringBuffer sb = new StringBuffer();
-        
+
         sb.append( "[\"" + getDestination() + "\" " );
         sb.append( "{" + getAttrString() + "}" );
-        
+
         if ( isDirOnly() )
         {
             sb.append( " (dir only)]" );
@@ -372,7 +399,7 @@
             }
             sb.append( "]" );
         }
-        
+
         return sb.toString();
     }
 }

