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 }