1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.ldap.client.template;
21
22
23 import java.nio.ByteBuffer;
24 import java.nio.CharBuffer;
25 import java.nio.charset.Charset;
26 import java.util.Arrays;
27
28
29
30
31
32
33
34
35
36
37 public class MemoryClearingBuffer
38 {
39 private static final Charset UTF8 = Charset.forName( "UTF-8" );
40 private byte[] computedBytes;
41 private char[] computedChars;
42 private byte[] originalBytes;
43 private char[] originalChars;
44 private char[] precomputedChars;
45
46
47 private MemoryClearingBuffer( byte[] originalBytes, char[] originalChars, boolean trim, boolean lowerCase )
48 {
49 this.originalBytes = originalBytes;
50 this.originalChars = originalChars;
51
52 if ( trim || lowerCase )
53 {
54 if ( this.originalChars == null )
55 {
56 throw new UnsupportedOperationException( "trim and lowerCase only applicable to char[]" );
57 }
58
59 char[] working = Arrays.copyOf( originalChars, originalChars.length );
60 int startIndex = 0;
61 int endIndex = working.length;
62
63 if ( trim )
64 {
65
66 for ( ; startIndex < working.length; startIndex++ )
67 {
68 if ( !Character.isWhitespace( working[startIndex] ) )
69 break;
70 }
71
72
73 for ( endIndex--; endIndex > startIndex; endIndex-- )
74 {
75 if ( !Character.isWhitespace( working[endIndex] ) )
76 break;
77 }
78 endIndex++;
79 }
80
81 if ( lowerCase )
82 {
83
84 for ( int i = startIndex; i < endIndex; i++ )
85 {
86 working[i] = Character.toLowerCase( working[i] );
87 }
88 }
89
90 this.precomputedChars = new char[endIndex - startIndex];
91 System.arraycopy( working, startIndex, this.precomputedChars, 0, endIndex - startIndex );
92 }
93 else
94 {
95 this.precomputedChars = this.originalChars;
96 }
97 }
98
99
100
101
102
103
104
105
106
107 public static MemoryClearingBuffer newInstance( byte[] bytes )
108 {
109 return new MemoryClearingBuffer( bytes, null, false, false );
110 }
111
112
113
114
115
116
117
118
119
120 public static MemoryClearingBuffer newInstance( char[] chars )
121 {
122 return new MemoryClearingBuffer( null, chars, false, false );
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public static MemoryClearingBuffer newInstance( char[] chars, boolean trim, boolean lowerCase )
138 {
139 return new MemoryClearingBuffer( null, chars, trim, lowerCase );
140 }
141
142
143
144
145
146 public void clear()
147 {
148
149 if ( computedBytes != null )
150 {
151 Arrays.fill( computedBytes, ( byte ) 0 );
152 }
153 if ( computedChars != null )
154 {
155 Arrays.fill( computedChars, '0' );
156 }
157 if ( precomputedChars != null )
158 {
159 Arrays.fill( precomputedChars, '0' );
160 }
161
162 computedBytes = null;
163 computedChars = null;
164 originalBytes = null;
165 originalChars = null;
166 precomputedChars = null;
167 }
168
169
170
171
172
173
174
175
176 byte[] getComputedBytes()
177 {
178 if ( computedBytes == null )
179 {
180 ByteBuffer byteBuffer = UTF8.encode(
181 CharBuffer.wrap( precomputedChars, 0, precomputedChars.length ) );
182 computedBytes = new byte[byteBuffer.remaining()];
183 byteBuffer.get( computedBytes );
184
185
186 byteBuffer.flip();
187 byte[] nullifier = new byte[byteBuffer.limit()];
188 Arrays.fill( nullifier, ( byte ) 0 );
189 byteBuffer.put( nullifier );
190 }
191 return computedBytes;
192 }
193
194
195
196
197
198
199
200
201 private char[] getComputedChars()
202 {
203 if ( computedChars == null )
204 {
205 CharBuffer charBuffer = UTF8.decode(
206 ByteBuffer.wrap( originalBytes, 0, originalBytes.length ) );
207 computedChars = new char[charBuffer.remaining()];
208 charBuffer.get( computedChars );
209
210
211 charBuffer.flip();
212 char[] nullifier = new char[charBuffer.limit()];
213 Arrays.fill( nullifier, ( char ) 0 );
214 charBuffer.put( nullifier );
215 }
216 return computedChars;
217 }
218
219
220
221
222
223
224
225
226 public byte[] getBytes()
227 {
228 return originalBytes == null
229 ? getComputedBytes()
230 : originalBytes;
231 }
232
233
234
235
236
237
238
239 public char[] getChars()
240 {
241 return precomputedChars == null
242 ? getComputedChars()
243 : precomputedChars;
244 }
245 }