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