View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.assembly.format;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.InputStreamReader;
24  import java.io.Reader;
25  import java.util.LinkedHashSet;
26  import java.util.List;
27  import java.util.Properties;
28  import java.util.Set;
29  
30  import org.apache.commons.io.input.ReaderInputStream;
31  import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
32  import org.apache.maven.plugins.assembly.utils.AssemblyFileUtils;
33  import org.apache.maven.plugins.assembly.utils.LineEndings;
34  import org.apache.maven.plugins.assembly.utils.LineEndingsUtils;
35  import org.apache.maven.shared.filtering.MavenFilteringException;
36  import org.apache.maven.shared.filtering.MavenReaderFilterRequest;
37  import org.codehaus.plexus.components.io.functions.InputStreamTransformer;
38  import org.codehaus.plexus.components.io.resources.PlexusIoResource;
39  
40  /**
41   *
42   */
43  public class ReaderFormatter {
44      private static Reader createReaderFilter(
45              Reader source,
46              String escapeString,
47              List<String> delimiters,
48              AssemblerConfigurationSource configSource,
49              boolean isPropertiesFile,
50              Properties additionalProperties)
51              throws IOException {
52          try {
53  
54              MavenReaderFilterRequest filterRequest = new MavenReaderFilterRequest(
55                      source,
56                      true,
57                      configSource.getProject(),
58                      configSource.getFilters(),
59                      isPropertiesFile,
60                      configSource.getMavenSession(),
61                      additionalProperties);
62  
63              filterRequest.setEscapeString(escapeString);
64  
65              // if these are NOT set, just use the defaults, which are '${*}' and '@'.
66              if (delimiters != null && !delimiters.isEmpty()) {
67                  LinkedHashSet<String> delims = new LinkedHashSet<>();
68                  for (String delim : delimiters) {
69                      if (delim == null) {
70                          // FIXME: ${filter:*} could also trigger this condition. Need a better long-term solution.
71                          delims.add("${*}");
72                      } else {
73                          delims.add(delim);
74                      }
75                  }
76  
77                  filterRequest.setDelimiters(delims);
78              } else {
79                  filterRequest.setDelimiters(filterRequest.getDelimiters());
80              }
81  
82              filterRequest.setInjectProjectBuildFilters(configSource.isIncludeProjectBuildFilters());
83              return configSource.getMavenReaderFilter().filter(filterRequest);
84          } catch (MavenFilteringException e) {
85              throw new IOException("Error filtering file '" + source + "': " + e.getMessage(), e);
86          }
87      }
88  
89      private static boolean isForbiddenFiletypes(PlexusIoResource plexusIoResource) {
90          String fileName = plexusIoResource.getName().toLowerCase();
91          return (fileName.endsWith(".zip") || fileName.endsWith(".jar"));
92      }
93  
94      private static void checkifFileTypeIsAppropriateForLineEndingTransformation(PlexusIoResource plexusIoResource)
95              throws IOException {
96          if (isForbiddenFiletypes(plexusIoResource)) {
97              throw new IOException("Cannot transform line endings on this kind of file: " + plexusIoResource.getName()
98                      + "\nDoing so is more or less guaranteed to destroy the file, and it indicates"
99                      + " a problem with your assembly descriptor."
100                     + "\nThis error message is new as of 2.5.3. "
101                     + "\nEarlier versions of assembly-plugin will silently destroy your file. "
102                     + "Fix your descriptor");
103         }
104     }
105 
106     public static InputStreamTransformer getFileSetTransformers(
107             final AssemblerConfigurationSource configSource,
108             final boolean isFiltered,
109             final Set<String> nonFilteredFileExtensions,
110             String fileSetLineEnding)
111             throws AssemblyFormattingException {
112         final LineEndings lineEndingToUse = LineEndingsUtils.getLineEnding(fileSetLineEnding);
113 
114         final boolean transformLineEndings = !LineEndings.keep.equals(lineEndingToUse);
115 
116         if (transformLineEndings || isFiltered) {
117             return new InputStreamTransformer() {
118                 @Override
119                 public InputStream transform(PlexusIoResource plexusIoResource, InputStream inputStream)
120                         throws IOException {
121                     final String fileName = plexusIoResource.getName();
122                     for (String extension : nonFilteredFileExtensions) {
123                         if (fileName.endsWith('.' + extension)) {
124                             return inputStream;
125                         }
126                     }
127 
128                     InputStream result = inputStream;
129                     if (isFiltered) {
130                         boolean isPropertyFile = AssemblyFileUtils.isPropertyFile(plexusIoResource.getName());
131                         final String encoding = isPropertyFile ? "ISO-8859-1" : configSource.getEncoding();
132 
133                         Reader source = encoding != null
134                                 ? new InputStreamReader(inputStream, encoding)
135                                 : new InputStreamReader(inputStream); // wtf platform encoding ? TODO: Fix this
136                         Reader filtered = createReaderFilter(
137                                 source,
138                                 configSource.getEscapeString(),
139                                 configSource.getDelimiters(),
140                                 configSource,
141                                 isPropertyFile,
142                                 configSource.getAdditionalProperties());
143                         result = ReaderInputStream.builder()
144                                 .setReader(filtered)
145                                 .setCharset(encoding)
146                                 .get();
147                     }
148                     if (transformLineEndings) {
149                         checkifFileTypeIsAppropriateForLineEndingTransformation(plexusIoResource);
150                         result = LineEndingsUtils.lineEndingConverter(result, lineEndingToUse);
151                     }
152                     return result;
153                 }
154             };
155         }
156         return null;
157     }
158 }