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 }