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 }