View Javadoc
1   package org.apache.maven.plugins.assembly.format;
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.commons.io.input.ReaderInputStream;
23  import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
24  import org.apache.maven.plugins.assembly.utils.AssemblyFileUtils;
25  import org.apache.maven.plugins.assembly.utils.LineEndings;
26  import org.apache.maven.plugins.assembly.utils.LineEndingsUtils;
27  import org.apache.maven.shared.filtering.MavenFilteringException;
28  import org.apache.maven.shared.filtering.MavenReaderFilterRequest;
29  import org.codehaus.plexus.components.io.functions.InputStreamTransformer;
30  import org.codehaus.plexus.components.io.resources.PlexusIoResource;
31  
32  import javax.annotation.Nonnull;
33  import javax.annotation.Nullable;
34  import java.io.IOException;
35  import java.io.InputStream;
36  import java.io.InputStreamReader;
37  import java.io.Reader;
38  import java.util.LinkedHashSet;
39  import java.util.List;
40  import java.util.Properties;
41  import java.util.Set;
42  
43  /**
44   *
45   */
46  public class ReaderFormatter
47  {
48      private static Reader createReaderFilter( @Nonnull Reader source, String escapeString, List<String> delimiters,
49                                                AssemblerConfigurationSource configSource, boolean isPropertiesFile,
50                                                Properties additionalProperties )
51          throws IOException
52      {
53          try
54          {
55  
56              MavenReaderFilterRequest filterRequest =
57                  new MavenReaderFilterRequest( source, true, configSource.getProject(), configSource.getFilters(),
58                                                isPropertiesFile, configSource.getMavenSession(), additionalProperties );
59              
60              filterRequest.setEscapeString( escapeString );
61  
62              // if these are NOT set, just use the defaults, which are '${*}' and '@'.
63              if ( delimiters != null && !delimiters.isEmpty() )
64              {
65                  LinkedHashSet<String> delims = new LinkedHashSet<>();
66                  for ( String delim : delimiters )
67                  {
68                      if ( delim == null )
69                      {
70                          // FIXME: ${filter:*} could also trigger this condition. Need a better long-term solution.
71                          delims.add( "${*}" );
72                      }
73                      else
74                      {
75                          delims.add( delim );
76                      }
77                  }
78  
79                  filterRequest.setDelimiters( delims );
80              }
81              else
82              {
83                  filterRequest.setDelimiters( filterRequest.getDelimiters() );
84              }
85  
86              filterRequest.setInjectProjectBuildFilters( configSource.isIncludeProjectBuildFilters() );
87              return configSource.getMavenReaderFilter().filter( filterRequest );
88          }
89          catch ( MavenFilteringException e )
90          {
91              IOException ioe = new IOException( "Error filtering file '" + source + "': " + e.getMessage(), e );
92              throw ioe;
93          }
94      }
95  
96  
97      private static boolean isForbiddenFiletypes( PlexusIoResource plexusIoResource )
98      {
99          String fileName = plexusIoResource.getName().toLowerCase();
100         return ( fileName.endsWith( ".zip" ) || fileName.endsWith( ".jar" ) );
101     }
102 
103     private static void checkifFileTypeIsAppropriateForLineEndingTransformation( PlexusIoResource plexusIoResource )
104         throws IOException
105     {
106         if ( isForbiddenFiletypes( plexusIoResource ) )
107         {
108             throw new IOException( "Cannot transform line endings on this kind of file: " + plexusIoResource.getName()
109                                        + "\nDoing so is more or less guaranteed to destroy the file, and it indicates"
110                                        + " a problem with your assembly descriptor."
111                                        + "\nThis error message is new as of 2.5.3. "
112                                        + "\nEarlier versions of assembly-plugin will silently destroy your file. "
113                                        + "Fix your descriptor" );
114         }
115 
116     }
117 
118     @Nullable
119     public static InputStreamTransformer getFileSetTransformers( final AssemblerConfigurationSource configSource,
120                                                                  final boolean isFiltered,
121                                                                  final Set<String> nonFilteredFileExtensions,
122                                                                  String fileSetLineEnding )
123         throws AssemblyFormattingException
124     {
125         final LineEndings lineEndingToUse = LineEndingsUtils.getLineEnding( fileSetLineEnding );
126 
127         final boolean transformLineEndings = !LineEndings.keep.equals( lineEndingToUse );
128 
129         if ( transformLineEndings || isFiltered )
130         {
131             return new InputStreamTransformer()
132             {
133                 @Override
134                 @Nonnull
135                 public InputStream transform( @Nonnull PlexusIoResource plexusIoResource,
136                                               @Nonnull InputStream inputStream )
137                     throws IOException
138                 {
139                     final String fileName = plexusIoResource.getName();
140                     for ( String extension : nonFilteredFileExtensions )
141                     {
142                         if ( fileName.endsWith( '.' + extension ) )
143                         {
144                             return inputStream;
145                         }
146                     }
147                     
148                     InputStream result = inputStream;
149                     if ( isFiltered )
150                     {
151                         boolean isPropertyFile = AssemblyFileUtils.isPropertyFile( plexusIoResource.getName() );
152                         final String encoding = isPropertyFile ? "ISO-8859-1" : configSource.getEncoding();
153 
154                         Reader source = encoding != null
155                             ? new InputStreamReader( inputStream, encoding )
156                             : new InputStreamReader( inputStream ); // wtf platform encoding ? TODO: Fix this
157                         Reader filtered =
158                             createReaderFilter( source, configSource.getEscapeString(), configSource.getDelimiters(),
159                                                 configSource, isPropertyFile, configSource.getAdditionalProperties() );
160                         result = encoding != null
161                             ? new ReaderInputStream( filtered, encoding )
162                             : new ReaderInputStream( filtered );
163                     }
164                     if ( transformLineEndings )
165                     {
166                         checkifFileTypeIsAppropriateForLineEndingTransformation( plexusIoResource );
167                         result = LineEndingsUtils.lineEndingConverter( result, lineEndingToUse );
168                     }
169                     return result;
170                 }
171             };
172         }
173         return null;
174     }
175 }