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