View Javadoc
1   package org.apache.maven.plugins.assembly.utils;
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 java.io.BufferedReader;
23  import java.io.BufferedWriter;
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileOutputStream;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.InputStreamReader;
30  import java.io.OutputStreamWriter;
31  import java.io.RandomAccessFile;
32  
33  import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
34  
35  /**
36   * Line Ending class which contains convenience methods to change line endings.
37   */
38  public final class LineEndingsUtils
39  {
40  
41      private LineEndingsUtils()
42      {
43          // prevent creations of instances.
44      }
45  
46      /**
47       * Converts the line endings of a file, writing a new file. The encoding of reading and writing can be specified.
48       *
49       * @param source      The source file, not null
50       * @param dest        The destination file, not null
51       * @param lineEndings This is the result of the getLineEndingChars(..) method in this utility class; the actual
52       *                    line-ending characters, not null.
53       * @param atEndOfFile The end-of-file line ending, if true then the resulting file will have a new line at the end
54       *                    even if the input didn't have one, if false then the resulting file will have no new line at
55       *                    the end even if the input did have one, null to determine whether to have a new line at the
56       *                    end of the file based on the input file
57       * @param encoding    The encoding to use, null for platform encoding
58       * @throws IOException .
59       */
60      public static void convertLineEndings( final File source, File dest, LineEndings lineEndings,
61                                             final Boolean atEndOfFile, String encoding )
62          throws IOException
63      {
64          // MASSEMBLY-637, MASSEMBLY-96
65          // find characters at the end of the file
66          // needed to preserve the last line ending
67          // only check for LF (as CRLF also ends in LF)
68          String eofChars = "";
69          if ( atEndOfFile == null )
70          {
71              if ( source.length() >= 1 )
72              {
73                  try ( RandomAccessFile raf = new RandomAccessFile( source, "r" ) )
74                  {
75                      raf.seek( source.length() - 1 );
76                      byte last = raf.readByte();
77                      if ( last == '\n' )
78                      {
79                          eofChars = lineEndings.getLineEndingCharacters();
80                      }
81                  }
82              }
83          }
84          else if ( atEndOfFile )
85          {
86              eofChars = lineEndings.getLineEndingCharacters();
87          }
88  
89          try ( BufferedReader in = getBufferedReader( source, encoding );
90                BufferedWriter out = getBufferedWriter( dest, encoding ) )
91          {
92              String line = in.readLine();
93              while ( line != null )
94              {
95                  out.write( line );
96                  line = in.readLine();
97                  if ( line != null )
98                  {
99                      out.write( lineEndings.getLineEndingCharacters() );
100                 }
101                 else
102                 {
103                     out.write( eofChars );
104                 }
105             }
106         }
107     }
108 
109     private static BufferedReader getBufferedReader( File source, String encoding ) throws IOException
110     {
111         if ( encoding == null )
112         {
113             // platform encoding
114             return new BufferedReader( new InputStreamReader( new FileInputStream( source ) ) );
115         }
116         else
117         {
118             // MASSEMBLY-371
119             return new BufferedReader( new InputStreamReader( new FileInputStream( source ), encoding ) );
120         }
121     }
122 
123     private static BufferedWriter getBufferedWriter( File dest, String encoding ) throws IOException
124     {
125         if ( encoding == null )
126         {
127             // platform encoding
128             return new BufferedWriter( new OutputStreamWriter( new FileOutputStream( dest ) ) );
129         }
130         else
131         {
132             // MASSEMBLY-371
133             return new BufferedWriter( new OutputStreamWriter( new FileOutputStream( dest ), encoding ) );
134         }
135     }
136 
137     /**
138      * Converts the line endings of a file, writing a new file. The encoding of reading and writing can be specified.
139      *
140      * @param in          The source reader
141      * @param lineEndings This is the result of the getLineEndingChars(..) method in this utility class; the actual
142      *                    line-ending characters, not null.
143      * @return an input stream that enforces a specifi line ending style
144      */
145     @SuppressWarnings( "resource" )
146     public static InputStream lineEndingConverter( InputStream in, LineEndings lineEndings )
147         throws IOException
148     {
149         return lineEndings.isNewLine()
150             ? new LinuxLineFeedInputStream( in, false )
151             : lineEndings.isCrLF() ? new WindowsLineFeedInputStream( in, false ) : in;
152     }
153 
154     public static LineEndings getLineEnding( /* nullable */ String lineEnding )
155         throws AssemblyFormattingException
156     {
157         LineEndings result = LineEndings.keep;
158         if ( lineEnding != null )
159         {
160             try
161             {
162                 result = LineEndings.valueOf( lineEnding );
163             }
164             catch ( IllegalArgumentException e )
165             {
166                 throw new AssemblyFormattingException( "Illegal lineEnding specified: '" + lineEnding + "'", e );
167             }
168         }
169         return result;
170     }
171 
172     /**
173      * Returns the appopriate line ending characters for the specified style
174      *
175      * @param lineEnding The name of the line ending style,
176      *                   see org.apache.maven.plugin.assembly.utils.LineEndings#valueOf
177      * @return The proper line ending characters
178      * @throws AssemblyFormattingException
179      */
180     public static String getLineEndingCharacters( /* nullable */ String lineEnding )
181         throws AssemblyFormattingException
182     {
183         String value = lineEnding;
184 
185         if ( lineEnding != null )
186         {
187             try
188             {
189                 value = LineEndings.valueOf( lineEnding ).getLineEndingCharacters();
190             }
191             catch ( IllegalArgumentException e )
192             {
193                 throw new AssemblyFormattingException( "Illegal lineEnding specified: '" + lineEnding + "'", e );
194             }
195         }
196 
197         return value;
198     }
199 
200 }