1 package org.apache.maven.plugins.enforcer.utils;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.FilterReader;
23 import java.io.IOException;
24 import java.io.Reader;
25
26
27
28
29 public class NormalizeLineSeparatorReader
30 extends FilterReader
31 {
32
33 private static final int EOL = -1;
34
35
36
37
38 public enum LineSeparator
39 {
40 WINDOWS( "\r\n", null ), UNIX( "\n", '\r' );
41
42 private final char[] separatorChars;
43
44 private final Character notPrecededByChar;
45
46 LineSeparator( String separator, Character notPrecededByChar )
47 {
48 separatorChars = separator.toCharArray();
49 this.notPrecededByChar = notPrecededByChar;
50 }
51
52 enum MatchResult
53 {
54 NO_MATCH,
55 POTENTIAL_MATCH,
56 MATCH;
57 }
58
59
60
61
62
63
64
65 public MatchResult matches( char currentCharacter, Character previousCharacter )
66 {
67 int len = separatorChars.length;
68 if ( currentCharacter == separatorChars[len - 1] )
69 {
70 if ( len > 1 )
71 {
72 if ( previousCharacter == null || previousCharacter != separatorChars[len - 1] )
73 {
74 return MatchResult.NO_MATCH;
75 }
76 }
77 if ( notPrecededByChar != null )
78 {
79 if ( previousCharacter != null && notPrecededByChar == previousCharacter )
80 {
81 return MatchResult.NO_MATCH;
82 }
83 }
84 return MatchResult.MATCH;
85 }
86 else if ( len > 1 && currentCharacter == separatorChars[len - 2] )
87 {
88 return MatchResult.POTENTIAL_MATCH;
89 }
90 return MatchResult.NO_MATCH;
91 }
92 };
93
94 final LineSeparator lineSeparator;
95
96 Character bufferedCharacter;
97
98 Character previousCharacter;
99
100 public NormalizeLineSeparatorReader( Reader reader, LineSeparator lineSeparator )
101 {
102 super( reader );
103 this.lineSeparator = lineSeparator;
104 bufferedCharacter = null;
105 }
106
107 @Override
108 public int read( char[] cbuf, int off, int len )
109 throws IOException
110 {
111 int n;
112 for ( n = off; n < off + len; n++ )
113 {
114 int readResult = read();
115 if ( readResult == EOL )
116 {
117 return n == 0 ? EOL : n;
118 }
119 else
120 {
121 cbuf[n] = (char) readResult;
122 }
123 }
124 return n;
125 }
126
127 @Override
128 public int read()
129 throws IOException
130 {
131
132 if ( bufferedCharacter != null )
133 {
134 char localBuffer = bufferedCharacter;
135 bufferedCharacter = null;
136 return localBuffer;
137 }
138 int readResult = super.read();
139 if ( readResult == EOL )
140 {
141 return readResult;
142 }
143 char currentCharacter = (char) readResult;
144 if ( lineSeparator == LineSeparator.UNIX )
145 {
146 switch ( LineSeparator.WINDOWS.matches( currentCharacter, previousCharacter ) )
147 {
148 case MATCH:
149 return lineSeparator.separatorChars[0];
150 case POTENTIAL_MATCH:
151 previousCharacter = currentCharacter;
152 return read();
153 default:
154
155 }
156 }
157 else
158 {
159
160 switch ( LineSeparator.UNIX.matches( currentCharacter, previousCharacter ) )
161 {
162 case MATCH:
163 bufferedCharacter = lineSeparator.separatorChars[1];
164
165 return lineSeparator.separatorChars[0];
166 case POTENTIAL_MATCH:
167
168 throw new IllegalStateException( "No potential matches expected for Unix line separator" );
169 default:
170
171 }
172 }
173 previousCharacter = currentCharacter;
174 return currentCharacter;
175 }
176
177 }