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 javax.annotation.Nonnull;
34  import javax.annotation.Nullable;
35  
36  import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
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                                             final 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              if ( source.length() >= 1 )
75              {
76                  try ( RandomAccessFile raf = new RandomAccessFile( source, "r" ) )
77                  {
78                      raf.seek( source.length() - 1 );
79                      byte last = raf.readByte();
80                      if ( last == '\n' )
81                      {
82                          eofChars = lineEndings.getLineEndingCharacters();
83                      }
84                  }
85              }
86          }
87          else if ( atEndOfFile )
88          {
89              eofChars = lineEndings.getLineEndingCharacters();
90          }
91  
92          try ( BufferedReader in = getBufferedReader( source, encoding );
93                BufferedWriter out = getBufferedWriter( dest, encoding ) )
94          {
95              String line = in.readLine();
96              while ( line != null )
97              {
98                  out.write( line );
99                  line = in.readLine();
100                 if ( line != null )
101                 {
102                     out.write( lineEndings.getLineEndingCharacters() );
103                 }
104                 else
105                 {
106                     out.write( eofChars );
107                 }
108             }
109         }
110     }
111 
112     private static BufferedReader getBufferedReader( File source, String encoding ) throws IOException
113     {
114         if ( encoding == null )
115         {
116             // platform encoding
117             return new BufferedReader( new InputStreamReader( new FileInputStream( source ) ) );
118         }
119         else
120         {
121             // MASSEMBLY-371
122             return new BufferedReader( new InputStreamReader( new FileInputStream( source ), encoding ) );
123         }
124     }
125 
126     private static BufferedWriter getBufferedWriter( File dest, String encoding ) throws IOException
127     {
128         if ( encoding == null )
129         {
130             // platform encoding
131             return new BufferedWriter( new OutputStreamWriter( new FileOutputStream( dest ) ) );
132         }
133         else
134         {
135             // MASSEMBLY-371
136             return new BufferedWriter( new OutputStreamWriter( new FileOutputStream( dest ), encoding ) );
137         }
138     }
139 
140     /**
141      * Converts the line endings of a file, writing a new file. The encoding of reading and writing can be specified.
142      *
143      * @param in          The source reader
144      * @param lineEndings This is the result of the getLineEndingChars(..) method in this utility class; the actual
145      *                    line-ending characters, not null.
146      * @return an input stream that enforces a specifi line ending style
147      */
148     @SuppressWarnings( "resource" )
149     public static InputStream lineEndingConverter( @Nonnull InputStream in, LineEndings lineEndings )
150         throws IOException
151     {
152         return lineEndings.isNewLine()
153             ? new LinuxLineFeedInputStream( in, false )
154             : lineEndings.isCrLF() ? new WindowsLineFeedInputStream( in, false ) : in;
155     }
156 
157     @Nonnull
158     public static LineEndings getLineEnding( @Nullable String lineEnding )
159         throws AssemblyFormattingException
160     {
161         LineEndings result = LineEndings.keep;
162         if ( lineEnding != null )
163         {
164             try
165             {
166                 result = LineEndings.valueOf( lineEnding );
167             }
168             catch ( IllegalArgumentException e )
169             {
170                 throw new AssemblyFormattingException( "Illegal lineEnding specified: '" + lineEnding + "'", e );
171             }
172         }
173         return result;
174     }
175 
176     /**
177      * Returns the appopriate line ending characters for the specified style
178      *
179      * @param lineEnding The name of the line ending style,
180      *                   see org.apache.maven.plugin.assembly.utils.LineEndings#valueOf
181      * @return The proper line ending characters
182      * @throws AssemblyFormattingException
183      */
184     @Nullable
185     public static String getLineEndingCharacters( @Nullable String lineEnding )
186         throws AssemblyFormattingException
187     {
188         String value = lineEnding;
189 
190         if ( lineEnding != null )
191         {
192             try
193             {
194                 value = LineEndings.valueOf( lineEnding ).getLineEndingCharacters();
195             }
196             catch ( IllegalArgumentException e )
197             {
198                 throw new AssemblyFormattingException( "Illegal lineEnding specified: '" + lineEnding + "'", e );
199             }
200         }
201 
202         return value;
203     }
204 
205 }