View Javadoc
1   package org.apache.maven.plugin.assembly.archive.task;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
23  import org.apache.maven.plugin.assembly.archive.ArchiveCreationException;
24  import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
25  import org.apache.maven.plugin.assembly.format.ReaderFormatter;
26  import org.apache.maven.plugin.assembly.model.FileSet;
27  import org.apache.maven.plugin.assembly.utils.AssemblyFormatUtils;
28  import org.apache.maven.plugin.assembly.utils.TypeConversionUtils;
29  import org.apache.maven.project.MavenProject;
30  import org.apache.maven.shared.utils.Os;
31  import org.codehaus.plexus.archiver.Archiver;
32  import org.codehaus.plexus.components.io.functions.InputStreamTransformer;
33  import org.codehaus.plexus.logging.Logger;
34  import org.codehaus.plexus.logging.console.ConsoleLogger;
35  
36  import java.io.File;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.List;
40  
41  /**
42   * @version $Id: AddFileSetsTask.java 1645049 2014-12-12 19:45:43Z krosenvold $
43   */
44  public class AddFileSetsTask
45  {
46  
47      private final List<FileSet> fileSets;
48  
49      private Logger logger;
50  
51      private MavenProject project;
52  
53      private MavenProject moduleProject;
54  
55      public AddFileSetsTask( final List<FileSet> fileSets )
56      {
57          this.fileSets = fileSets;
58      }
59  
60      public AddFileSetsTask( final FileSet... fileSets )
61      {
62          this.fileSets = new ArrayList<FileSet>( Arrays.asList( fileSets ) );
63      }
64  
65      public void execute( final Archiver archiver, final AssemblerConfigurationSource configSource )
66          throws ArchiveCreationException, AssemblyFormattingException
67      {
68          // don't need this check here. it's more efficient here, but the logger is not actually
69          // used until addFileSet(..)...and the check should be there in case someone extends the
70          // class.
71          // checkLogger();
72  
73          final File archiveBaseDir = configSource.getArchiveBaseDirectory();
74  
75          if ( archiveBaseDir != null )
76          {
77              if ( !archiveBaseDir.exists() )
78              {
79                  throw new ArchiveCreationException(
80                      "The archive base directory '" + archiveBaseDir.getAbsolutePath() + "' does not exist" );
81              }
82              else if ( !archiveBaseDir.isDirectory() )
83              {
84                  throw new ArchiveCreationException( "The archive base directory '" + archiveBaseDir.getAbsolutePath()
85                                                          + "' exists, but it is not a directory" );
86              }
87          }
88  
89          for ( final FileSet fileSet : fileSets )
90          {
91              addFileSet( fileSet, archiver, configSource, archiveBaseDir );
92          }
93      }
94  
95      void addFileSet( final FileSet fileSet, final Archiver archiver, final AssemblerConfigurationSource configSource,
96                       final File archiveBaseDir )
97          throws AssemblyFormattingException, ArchiveCreationException
98      {
99          // throw this check in just in case someone extends this class...
100         checkLogger();
101 
102         if ( project == null )
103         {
104             project = configSource.getProject();
105         }
106 
107         final File basedir = project.getBasedir();
108 
109         String destDirectory = fileSet.getOutputDirectory();
110 
111         if ( destDirectory == null )
112         {
113             destDirectory = fileSet.getDirectory();
114         }
115 
116         warnForPlatformSpecifics( destDirectory );
117 
118         destDirectory =
119             AssemblyFormatUtils.getOutputDirectory( destDirectory, configSource.getFinalName(), configSource,
120                                                     AssemblyFormatUtils.moduleProjectInterpolator( moduleProject ),
121                                                     AssemblyFormatUtils.artifactProjectInterpolator( project ) );
122 
123         if ( logger.isDebugEnabled() )
124         {
125             logger.debug( "FileSet[" + destDirectory + "]" + " dir perms: " + Integer.toString(
126                 archiver.getOverrideDirectoryMode(), 8 ) + " file perms: " + Integer.toString(
127                 archiver.getOverrideFileMode(), 8 ) + ( fileSet.getLineEnding() == null
128                 ? ""
129                 : " lineEndings: " + fileSet.getLineEnding() ) );
130         }
131 
132         logger.debug( "The archive base directory is '" + archiveBaseDir + "'" );
133 
134         File fileSetDir = getFileSetDirectory( fileSet, basedir, archiveBaseDir );
135 
136         if ( fileSetDir.exists() )
137         {
138             InputStreamTransformer fileSetTransformers =
139                 ReaderFormatter.getFileSetTransformers( configSource, fileSet.isFiltered(), fileSet.getLineEnding() );
140             if ( fileSetTransformers == null )
141             {
142                 logger.debug( "NOT reformatting any files in " + fileSetDir );
143             }
144 
145             if ( fileSetDir.getPath().equals( File.separator ) )
146             {
147                 throw new AssemblyFormattingException(
148                     "Your assembly descriptor specifies a directory of " + File.separator
149                         + ", which is your *entire* file system.\nThese are not the files you are looking for" );
150             }
151             final AddDirectoryTask task = new AddDirectoryTask( fileSetDir, fileSetTransformers );
152 
153             final int dirMode = TypeConversionUtils.modeToInt( fileSet.getDirectoryMode(), logger );
154             if ( dirMode != -1 )
155             {
156                 task.setDirectoryMode( dirMode );
157             }
158 
159             final int fileMode = TypeConversionUtils.modeToInt( fileSet.getFileMode(), logger );
160             if ( fileMode != -1 )
161             {
162                 task.setFileMode( fileMode );
163             }
164 
165             task.setUseDefaultExcludes( fileSet.isUseDefaultExcludes() );
166 
167             final List<String> excludes = fileSet.getExcludes();
168             excludes.add( "**/*.filtered" );
169             excludes.add( "**/*.formatted" );
170             task.setExcludes( excludes );
171 
172             task.setIncludes( fileSet.getIncludes() );
173             task.setOutputDirectory( destDirectory );
174 
175             task.execute( archiver );
176         }
177     }
178 
179     private void warnForPlatformSpecifics( String destDirectory )
180     {
181         if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
182         {
183             if ( isLinuxRootReference( destDirectory ) )
184             {
185                 logger.error( "OS=Windows and the assembly descriptor contains a *nix-specific root-relative-reference"
186                                   + " (starting with slash) " + destDirectory );
187             }
188             else if ( isWindowsPath( destDirectory ) )
189             {
190                 logger.warn( "The assembly descriptor contains a *nix-specific root-relative-reference"
191                                  + " (starting with slash). This is non-portable and will fail on windows "
192                                  + destDirectory );
193             }
194         }
195         else
196         {
197             if ( isWindowsPath( destDirectory ) )
198             {
199                 logger.error(
200                     "OS=Non-Windows and the assembly descriptor contains a windows-specific directory reference"
201                         + " (with a drive letter) " + destDirectory );
202             }
203             else if ( isLinuxRootReference( destDirectory ) )
204             {
205                 logger.warn( "The assembly descriptor contains a filesystem-root relative reference,"
206                                  + "which is not cross platform compatible " + destDirectory );
207             }
208         }
209     }
210 
211     static boolean isWindowsPath( String destDirectory )
212     {
213         return ( destDirectory != null && destDirectory.length() >= 2 && destDirectory.charAt( 1 ) == ':' );
214     }
215 
216     static boolean isLinuxRootReference( String destDirectory )
217     {
218         return ( destDirectory != null && destDirectory.startsWith( "/" ) );
219     }
220 
221     File getFileSetDirectory( final FileSet fileSet, final File basedir, final File archiveBaseDir )
222         throws ArchiveCreationException, AssemblyFormattingException
223     {
224         String sourceDirectory = fileSet.getDirectory();
225 
226         if ( sourceDirectory == null || sourceDirectory.trim().length() < 1 )
227         {
228             sourceDirectory = basedir.getAbsolutePath();
229         }
230 
231         File fileSetDir;
232 
233         if ( archiveBaseDir == null )
234         {
235             fileSetDir = new File( sourceDirectory );
236 
237             if ( !fileSetDir.isAbsolute() )
238             {
239                 fileSetDir = new File( basedir, sourceDirectory );
240             }
241         }
242         else
243         {
244             fileSetDir = new File( archiveBaseDir, sourceDirectory );
245         }
246 
247         return fileSetDir;
248     }
249 
250     private void checkLogger()
251     {
252         if ( logger == null )
253         {
254             logger = new ConsoleLogger( Logger.LEVEL_INFO, "AddFileSetsTask-internal" );
255         }
256     }
257 
258     public void setLogger( final Logger logger )
259     {
260         this.logger = logger;
261     }
262 
263     public void setProject( final MavenProject project )
264     {
265         this.project = project;
266     }
267 
268     public void setModuleProject( final MavenProject moduleProject )
269     {
270         this.moduleProject = moduleProject;
271     }
272 
273 }