Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ResourcesBase |
|
| 4.611111111111111;4.611 |
1 | /* | |
2 | * $Id: ResourcesBase.java 354330 2005-12-06 06:05:19Z niallp $ | |
3 | * $Revision: 354330 $ | |
4 | * $Date: 2005-12-06 06:05:19 +0000 (Tue, 06 Dec 2005) $ | |
5 | * | |
6 | * ==================================================================== | |
7 | * | |
8 | * Copyright 2003-2005 The Apache Software Foundation | |
9 | * | |
10 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
11 | * you may not use this file except in compliance with the License. | |
12 | * You may obtain a copy of the License at | |
13 | * | |
14 | * http://www.apache.org/licenses/LICENSE-2.0 | |
15 | * | |
16 | * Unless required by applicable law or agreed to in writing, software | |
17 | * distributed under the License is distributed on an "AS IS" BASIS, | |
18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
19 | * See the License for the specific language governing permissions and | |
20 | * limitations under the License. | |
21 | * | |
22 | */ | |
23 | ||
24 | package org.apache.commons.resources.impl; | |
25 | ||
26 | import java.io.ByteArrayInputStream; | |
27 | import java.io.InputStream; | |
28 | import java.io.InputStreamReader; | |
29 | import java.io.Reader; | |
30 | import java.io.StringReader; | |
31 | import java.io.IOException; | |
32 | import java.util.Iterator; | |
33 | import java.util.Locale; | |
34 | ||
35 | import org.apache.commons.resources.Resources; | |
36 | import org.apache.commons.resources.ResourcesException; | |
37 | import org.apache.commons.resources.ResourcesKeyException; // for javadoc/checkstyle | |
38 | ||
39 | /** | |
40 | * <p>Convenience base class for | |
41 | * {@link org.apache.commons.resources.Resources} implementations.</p> | |
42 | * | |
43 | * <p>Default implementations of the content retrieval methods are provided | |
44 | * for all methods except <code>getObject()</code>. The default methods for | |
45 | * the other content retrieval methods are coded in terms of | |
46 | * <code>getString()</code>, on the assumption that most uses of | |
47 | * {@link org.apache.commons.resources.Resources} are of this type. | |
48 | * However, they can be easily overridden as needed.</p> | |
49 | * | |
50 | * @see org.apache.commons.resources.impl.CollectionResourcesBase | |
51 | * @see org.apache.commons.resources.impl.JDBCResources | |
52 | * @see org.apache.commons.resources.impl.PropertyResources | |
53 | * @see org.apache.commons.resources.impl.ResourceBundleResources | |
54 | * @see org.apache.commons.resources.impl.WebappPropertyResources | |
55 | * @see org.apache.commons.resources.impl.WebappXMLResources | |
56 | * @see org.apache.commons.resources.impl.XMLResources | |
57 | */ | |
58 | public abstract class ResourcesBase implements Resources { | |
59 | ||
60 | ||
61 | // ----------------------------------------------------------- Constructors | |
62 | ||
63 | ||
64 | /** | |
65 | * <p>Create a new {@link org.apache.commons.resources.Resources} instance | |
66 | * with no name.</p> | |
67 | */ | |
68 | public ResourcesBase() { | |
69 | ||
70 | 0 | this(null); |
71 | ||
72 | 0 | } |
73 | ||
74 | ||
75 | /** | |
76 | * <p>Create a new {@link org.apache.commons.resources.Resources} instance | |
77 | * with the specified logical name.</p> | |
78 | * | |
79 | * @param name Logical name of the new instance | |
80 | */ | |
81 | 0 | public ResourcesBase(String name) { |
82 | ||
83 | 0 | this.name = name; |
84 | ||
85 | 0 | } |
86 | ||
87 | ||
88 | // ----------------------------------------------------- Instance Variables | |
89 | ||
90 | ||
91 | /** | |
92 | * <p>The logical name of this {@link org.apache.commons.resources.Resources} | |
93 | * instance.</p> | |
94 | */ | |
95 | 0 | private String name = null; |
96 | ||
97 | ||
98 | /** | |
99 | * <p>Flag indicating whether resource getter methods should return | |
100 | * <code>null</code> (instead of throwing an exception) on invalid | |
101 | * key values.</p> | |
102 | */ | |
103 | 0 | private boolean returnNull = true; |
104 | ||
105 | /** | |
106 | * Buffer size for creating char and byte arrays. | |
107 | */ | |
108 | 0 | private int bufferSize = 500; |
109 | ||
110 | // ------------------------------------------------------ Lifecycle Methods | |
111 | ||
112 | ||
113 | /** | |
114 | * <p>This must be called to initialize the data content of this | |
115 | * {@link org.apache.commons.resources.Resources} instance, before | |
116 | * any of the <code>getXxx()</code> methods are called.</p> | |
117 | * | |
118 | * <p>The default implementation does nothing.</p> | |
119 | * | |
120 | * @exception ResourcesException if an error occurs during initialization | |
121 | */ | |
122 | public void init() { | |
123 | ||
124 | // The default implementation does nothing | |
125 | ||
126 | 0 | } |
127 | ||
128 | ||
129 | /** | |
130 | * <p>This method must be called when the manager of this resource | |
131 | * decides that it's no longer needed. After this method is called, | |
132 | * no further calls to any of the <code>getXxx()</code> methods are | |
133 | * allowed.</p> | |
134 | * | |
135 | * <p>The default implementation does nothing.</p> | |
136 | * | |
137 | * @exception ResourcesException if an error occurs during finalization | |
138 | */ | |
139 | public void destroy() { | |
140 | ||
141 | // The default implementation does nothing | |
142 | ||
143 | 0 | } |
144 | ||
145 | ||
146 | // ------------------------------------------------------------- Properties | |
147 | ||
148 | ||
149 | /** | |
150 | * <p>Return an <code>Iterator</code> over the defined keys in this | |
151 | * {@link org.apache.commons.resources.Resources} instance.</p> | |
152 | * | |
153 | * @return The keys contained in this resources instance. | |
154 | */ | |
155 | public abstract Iterator getKeys(); | |
156 | ||
157 | ||
158 | /** | |
159 | * <p>Return the logical name of this {@link org.apache.commons.resources.Resources} | |
160 | * instance.</p> | |
161 | * | |
162 | * @return The name of this resources instance. | |
163 | */ | |
164 | public String getName() { | |
165 | ||
166 | 0 | return (this.name); |
167 | ||
168 | } | |
169 | ||
170 | ||
171 | /** | |
172 | * <p>Return <code>true</code> if resource getter methods will return | |
173 | * <code>null</code> instead of throwing an exception on invalid | |
174 | * key values.</p> | |
175 | * @return 'true' if null is returned for invalid key values. | |
176 | */ | |
177 | public boolean isReturnNull() { | |
178 | ||
179 | 0 | return (this.returnNull); |
180 | ||
181 | } | |
182 | ||
183 | ||
184 | /** | |
185 | * <p>Set a flag determining whether resource getter methods should | |
186 | * return <code>null</code> instead of throwing an exception on | |
187 | * invalid key values.</p> | |
188 | * | |
189 | * @param returnNull The new flag value | |
190 | */ | |
191 | public void setReturnNull(boolean returnNull) { | |
192 | ||
193 | 0 | this.returnNull = returnNull; |
194 | ||
195 | 0 | } |
196 | ||
197 | ||
198 | /** | |
199 | * <p>Return the size of the buffer to use when converting | |
200 | * InputStream or Reader objects.</p> | |
201 | * | |
202 | * @return The buffer size. | |
203 | */ | |
204 | public int getBufferSize() { | |
205 | ||
206 | 0 | return bufferSize; |
207 | ||
208 | } | |
209 | ||
210 | /** | |
211 | * <p>Set the size of the buffer to use when converting | |
212 | * InputStream or Reader objects.</p> | |
213 | * | |
214 | * @param bufferSize The buffer size. | |
215 | */ | |
216 | public void setBufferSize(int bufferSize) { | |
217 | ||
218 | 0 | this.bufferSize = bufferSize; |
219 | ||
220 | 0 | } |
221 | ||
222 | ||
223 | // ---------------------------------------------- Content Retrieval Methods | |
224 | ||
225 | ||
226 | /** | |
227 | * <p>Return the content for the specified <code>key</code> as a | |
228 | * byte array, localized based on the specified <code>locale</code>. | |
229 | * </p> | |
230 | * | |
231 | * <p>The default implementation calls <code>getString()</code> and | |
232 | * converts the value to a byte array.</p> | |
233 | * | |
234 | * @param key Identifier for the requested content | |
235 | * @param locale Locale with which to localize retrieval, | |
236 | * or <code>null</code> for the default Locale | |
237 | * @return content for a specified key. | |
238 | * | |
239 | * @exception ResourcesException if an error occurs retrieving or | |
240 | * returning the requested content | |
241 | * @exception ResourcesKeyException if the no value for the specified | |
242 | * key was found, and <code>isReturnNull()</code> returns | |
243 | * <code>false</code> | |
244 | */ | |
245 | public byte[] getBytes(String key, Locale locale) { | |
246 | ||
247 | 0 | Object value = getObject(key, locale); |
248 | 0 | if (value == null) { |
249 | 0 | return (null); |
250 | 0 | } else if (value instanceof String) { |
251 | 0 | return ((String)value).getBytes(); |
252 | 0 | } else if (value instanceof Reader) { |
253 | 0 | char[] chars = getChars((Reader)value); |
254 | 0 | if (chars == null) { |
255 | 0 | return (byte[])checkThrow(key); |
256 | } | |
257 | 0 | return new String(chars).getBytes(); |
258 | 0 | } else if (value instanceof InputStream) { |
259 | 0 | byte[] bytes = getBytes((InputStream)value); |
260 | 0 | if (bytes == null) { |
261 | 0 | return (byte[])checkThrow(key); |
262 | } | |
263 | 0 | return bytes; |
264 | 0 | } else if (value instanceof byte[]) { |
265 | 0 | return (byte[])value; |
266 | } else { | |
267 | 0 | return value.toString().getBytes(); |
268 | } | |
269 | ||
270 | } | |
271 | ||
272 | ||
273 | /** | |
274 | * <p>Return the content for the specified <code>key</code> as an | |
275 | * InputStream, localized based on the specified <code>locale</code>. | |
276 | * </p> | |
277 | * | |
278 | * <p>The default implementation calls <code>getsBytes()</code> | |
279 | * and returns an input stream over the resulting byte array.</p> | |
280 | * | |
281 | * @param key Identifier for the requested content | |
282 | * @param locale Locale with which to localize retrieval, | |
283 | * or <code>null</code> for the default Locale | |
284 | * @return content for a specified key. | |
285 | * | |
286 | * @exception ResourcesException if an error occurs retrieving or | |
287 | * returning the requested content | |
288 | * @exception ResourcesKeyException if the no value for the specified | |
289 | * key was found, and <code>isReturnNull()</code> returns | |
290 | * <code>false</code> | |
291 | */ | |
292 | public InputStream getInputStream(String key, Locale locale) { | |
293 | ||
294 | 0 | Object value = getObject(key, locale); |
295 | 0 | if (value == null) { |
296 | 0 | return (null); |
297 | 0 | } else if (value instanceof String) { |
298 | 0 | byte[] bytes = ((String)value).getBytes(); |
299 | 0 | return new ByteArrayInputStream(bytes); |
300 | 0 | } else if (value instanceof Reader) { |
301 | 0 | char[] chars = getChars((Reader)value); |
302 | 0 | if (chars == null) { |
303 | 0 | return (InputStream)checkThrow(key); |
304 | } | |
305 | 0 | byte[] bytes = (new String(chars)).getBytes(); |
306 | 0 | return new ByteArrayInputStream(bytes); |
307 | 0 | } else if (value instanceof InputStream) { |
308 | 0 | return (InputStream)value; |
309 | 0 | } else if (value instanceof byte[]) { |
310 | 0 | return new ByteArrayInputStream((byte[])value); |
311 | } else { | |
312 | 0 | byte[] bytes = value.toString().getBytes(); |
313 | 0 | return new ByteArrayInputStream(bytes); |
314 | } | |
315 | ||
316 | } | |
317 | ||
318 | ||
319 | /** | |
320 | * <p>Return the content for the specified <code>key</code> as an | |
321 | * Object, localized based on the specified <code>locale</code>. | |
322 | * </p> | |
323 | * | |
324 | * <p>There is no default implementation of this method. Concrete | |
325 | * subclasses must provide such an implementation.</p> | |
326 | * | |
327 | * @param key Identifier for the requested content | |
328 | * @param locale Locale with which to localize retrieval, | |
329 | * or <code>null</code> for the default Locale | |
330 | * @return content for a specified key. | |
331 | * | |
332 | * @exception ResourcesException if an error occurs retrieving or | |
333 | * returning the requested content | |
334 | * @exception ResourcesKeyException if the no value for the specified | |
335 | * key was found, and <code>isReturnNull()</code> returns | |
336 | * <code>false</code> | |
337 | */ | |
338 | public abstract Object getObject(String key, Locale locale); | |
339 | ||
340 | ||
341 | /** | |
342 | * <p>Return the content for the specified <code>key</code> as a | |
343 | * Reader, localized based on the specified <code>locale</code>. | |
344 | * </p> | |
345 | * | |
346 | * <p>The default implementation calls <code>getString()</code> | |
347 | * and returns a reader over the resulting characters.</p> | |
348 | * | |
349 | * @param key Identifier for the requested content | |
350 | * @param locale Locale with which to localize retrieval, | |
351 | * or <code>null</code> for the default Locale | |
352 | * @return content for a specified key. | |
353 | * | |
354 | * @exception ResourcesException if an error occurs retrieving or | |
355 | * returning the requested content | |
356 | * @exception ResourcesKeyException if the no value for the specified | |
357 | * key was found, and <code>isReturnNull()</code> returns | |
358 | * <code>false</code> | |
359 | */ | |
360 | public Reader getReader(String key, Locale locale) { | |
361 | ||
362 | 0 | Object value = getObject(key, locale); |
363 | 0 | if (value == null) { |
364 | 0 | return (null); |
365 | 0 | } else if (value instanceof String) { |
366 | 0 | return new StringReader((String)value); |
367 | 0 | } else if (value instanceof Reader) { |
368 | 0 | return (Reader)value; |
369 | 0 | } else if (value instanceof InputStream) { |
370 | 0 | return new InputStreamReader((InputStream)value); |
371 | 0 | } else if (value instanceof byte[]) { |
372 | 0 | InputStream bais = new ByteArrayInputStream((byte[])value); |
373 | 0 | return new InputStreamReader(bais); |
374 | } else { | |
375 | 0 | return new StringReader(value.toString()); |
376 | } | |
377 | ||
378 | } | |
379 | ||
380 | ||
381 | /** | |
382 | * <p>Return the content for the specified <code>key</code> as a | |
383 | * String, localized based on the specified <code>locale</code>. | |
384 | * </p> | |
385 | * | |
386 | * <p>The default implementation calls <code>getObject()</code> | |
387 | * and converts the result to a String if necessary.</p> | |
388 | * | |
389 | * @param key Identifier for the requested content | |
390 | * @param locale Locale with which to localize retrieval, | |
391 | * or <code>null</code> for the default Locale | |
392 | * @return content for a specified key. | |
393 | * | |
394 | * @exception ResourcesException if an error occurs retrieving or | |
395 | * returning the requested content | |
396 | * @exception ResourcesKeyException if the no value for the specified | |
397 | * key was found, and <code>isReturnNull()</code> returns | |
398 | * <code>false</code> | |
399 | */ | |
400 | public String getString(String key, Locale locale) { | |
401 | ||
402 | 0 | Object value = getObject(key, locale); |
403 | 0 | if (value == null) { |
404 | 0 | return (null); |
405 | 0 | } else if (value instanceof String) { |
406 | 0 | return ((String) value); |
407 | 0 | } else if (value instanceof Reader) { |
408 | 0 | char[] chars = getChars((Reader)value); |
409 | 0 | if (chars == null) { |
410 | 0 | return (String)checkThrow(key); |
411 | } | |
412 | 0 | return new String(chars); |
413 | 0 | } else if (value instanceof InputStream) { |
414 | 0 | byte[] bytes = getBytes((InputStream)value); |
415 | 0 | if (bytes == null) { |
416 | 0 | return (String)checkThrow(key); |
417 | } | |
418 | 0 | return new String(bytes); |
419 | 0 | } else if (value instanceof byte[]) { |
420 | 0 | return new String((byte[])value); |
421 | } else { | |
422 | 0 | return (value.toString()); |
423 | } | |
424 | ||
425 | } | |
426 | ||
427 | ||
428 | /** | |
429 | * Convert a Reader to a char array. | |
430 | */ | |
431 | private char[] getChars(Reader reader) { | |
432 | ||
433 | 0 | char[] array = null; |
434 | 0 | int arrayLth = 0; |
435 | try { | |
436 | while (true) { | |
437 | 0 | char[] buffer = new char[bufferSize]; |
438 | 0 | int bufferLth = reader.read(buffer); |
439 | 0 | if (bufferLth < 0) { |
440 | 0 | break; |
441 | } | |
442 | 0 | if (array == null && bufferLth == buffer.length) { |
443 | 0 | array = buffer; |
444 | } else { | |
445 | 0 | char[] newArray = new char[arrayLth + bufferLth]; |
446 | 0 | if (array != null) { |
447 | 0 | System.arraycopy(array, 0, newArray, 0, arrayLth); |
448 | } | |
449 | 0 | System.arraycopy(buffer, 0, newArray, arrayLth, bufferLth); |
450 | 0 | array = newArray; |
451 | } | |
452 | 0 | arrayLth = array.length; |
453 | 0 | } |
454 | 0 | } catch(IOException e) { |
455 | 0 | throw new ResourcesException("Error reading Reader", e); |
456 | 0 | } |
457 | ||
458 | 0 | return array; |
459 | ||
460 | } | |
461 | ||
462 | /** | |
463 | * Convert an InputStream to a byte array. | |
464 | */ | |
465 | private byte[] getBytes(InputStream inputStream) { | |
466 | ||
467 | 0 | byte[] array = null; |
468 | 0 | int arrayLth = 0; |
469 | try { | |
470 | while (true) { | |
471 | 0 | byte[] buffer = new byte[bufferSize]; |
472 | 0 | int bufferLth = inputStream.read(buffer); |
473 | 0 | if (bufferLth < 0) { |
474 | 0 | break; |
475 | } | |
476 | 0 | if (array == null && bufferLth == buffer.length) { |
477 | 0 | array = buffer; |
478 | } else { | |
479 | 0 | byte[] newArray = new byte[arrayLth + bufferLth]; |
480 | 0 | if (array != null) { |
481 | 0 | System.arraycopy(array, 0, newArray, 0, arrayLth); |
482 | } | |
483 | 0 | System.arraycopy(buffer, 0, newArray, arrayLth, bufferLth); |
484 | 0 | array = newArray; |
485 | } | |
486 | 0 | arrayLth = array.length; |
487 | 0 | } |
488 | 0 | } catch(IOException e) { |
489 | 0 | throw new ResourcesException("Error reading InputStream", e); |
490 | 0 | } |
491 | 0 | return array; |
492 | ||
493 | } | |
494 | ||
495 | /** | |
496 | * Check whether this Resources instance is | |
497 | * configured to return null or throw a ResourcesKeyException. | |
498 | * @param key Identifier for the requested content | |
499 | * @return 'null' if returnNull is 'true' otherwise throws | |
500 | * a ResourcesKeyException. | |
501 | */ | |
502 | private Object checkThrow(String key) { | |
503 | 0 | if (isReturnNull()) { |
504 | 0 | return (null); |
505 | } else { | |
506 | 0 | throw new ResourcesKeyException(key); |
507 | } | |
508 | } | |
509 | ||
510 | } |