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 }