Line | Hits | Source |
---|---|---|
1 | /* | |
2 | * Copyright (C) 2006 TopCoder Inc., All Rights Reserved. | |
3 | */ | |
4 | package com.topcoder.document.index.persistence.impl; | |
5 | ||
6 | import com.topcoder.document.index.persistence.IndexPersistenceException; | |
7 | import com.topcoder.document.index.wordsource.WordSourceId; | |
8 | import com.topcoder.util.config.ConfigManager; | |
9 | import com.topcoder.util.config.UnknownNamespaceException; | |
10 | ||
11 | import java.io.ByteArrayInputStream; | |
12 | import java.io.ByteArrayOutputStream; | |
13 | import java.io.IOException; | |
14 | import java.io.InputStream; | |
15 | import java.io.ObjectInputStream; | |
16 | import java.io.ObjectOutputStream; | |
17 | import java.security.MessageDigest; | |
18 | import java.security.NoSuchAlgorithmException; | |
19 | ||
20 | ||
21 | /** | |
22 | * This class contains utility methods used by the implementation of this component. This class needs to be public as | |
23 | * multiple packages of the component use the functionality provided by this class. | |
24 | * | |
25 | * @author TCSDEVELOPER | |
26 | * @version 1.0 | |
27 | */ | |
28 | public class Utils { | |
29 | /** | |
30 | * This constant is used as initial size for newly created {@link java.io.ByteArrayOutputStream}s during | |
31 | * serialization in {@link #serializeObject(Object)}. | |
32 | */ | |
33 | private static final int ONE_KILOBYTE = 1024; | |
34 | /** | |
35 | * These are the hex digits used in hex encoding a byte[] in {@link #createIdString(WordSourceId)}. | |
36 | */ | |
37 | 1 | private static final char[] HEX_DIGITS = { |
38 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | |
39 | /** | |
40 | * This constant is used as a mask to mask any high bytes of an int, so that the int is only made from the lowest | |
41 | * byte. | |
42 | */ | |
43 | private static final int ONE_BYTE_MASK = 0xff; | |
44 | /** | |
45 | * This mask is used when splitting a byte into its two nibbles for encoding them into hex digits. | |
46 | */ | |
47 | private static final int NIBBLE_MASK = 16; | |
48 | ||
49 | /** | |
50 | * As this class is a utility class, a private constructor is added to avoid class instantiation. | |
51 | */ | |
52 | 0 | private Utils() { |
53 | 0 | } |
54 | ||
55 | /** | |
56 | * This method looks up a configuration property from the {@link com.topcoder.util.config.ConfigManager} and parses | |
57 | * the value retrieved into an <tt>int</tt> value that is at least the specified minValue. | |
58 | * | |
59 | * @param namespace A non-<tt>null</tt>, non-empty (trim'd) string representing the {@link | |
60 | * com.topcoder.util.config.ConfigManager} namespace in which to lookup the configuration property | |
61 | * @param key A non-<tt>null</tt>, non-empty (trim'd) string representing the name of the property to be | |
62 | * looked up | |
63 | * @param minValue the minimum value of the <tt>int</tt> value parsed from the value looked up, a {@link | |
64 | * PersistenceConfigurationException} is thrown in case the value parsed is less than this value | |
65 | * | |
66 | * @return the <tt>int</tt> value looked up from the {@link com.topcoder.util.config.ConfigManager}, <tt>>=</tt> | |
67 | * the given minValue | |
68 | * | |
69 | * @throws IllegalArgumentException if namespace or key are empty (trim'd) strings | |
70 | * @throws PersistenceConfigurationException | |
71 | * in case the property lookup fails, returns <tt>null</tt>, is not parseable into | |
72 | * an <tt>int</tt> or is <tt><minValue</tt> | |
73 | */ | |
74 | public static int lookupIntFromConfigManager(final String namespace, final String key, final int minValue) | |
75 | throws PersistenceConfigurationException { | |
76 | 159 | final String value = lookupValidStringFromConfigManager(namespace, key); |
77 | final int ret; | |
78 | try { | |
79 | 154 | ret = Integer.parseInt(value); |
80 | 2 | } catch (NumberFormatException e) { |
81 | 2 | throw new PersistenceConfigurationException( |
82 | "The configuration value [" + value + "] for the property [" + key | |
83 | + "] in namespace [" + namespace + "] was not parseable into a valid number.", e); | |
84 | 152 | } |
85 | 152 | if (ret < minValue) { |
86 | 2 | throw new PersistenceConfigurationException("The configuration value [" + ret + "] for the property [" + key |
87 | + "] in namespace [" + namespace + "] was less than the minimum allowed value [" + minValue + "]."); | |
88 | } | |
89 | 150 | return ret; |
90 | } | |
91 | ||
92 | /** | |
93 | * This method looks up a configuration property of type {@link String} from the {@link ConfigManager}. The value | |
94 | * looked up is checked to be non-<tt>null</tt> an non-empty (trim'd). | |
95 | * | |
96 | * @param namespace A non-<tt>null</tt>, non-empty (trim'd) string representing the {@link ConfigManager} namespace | |
97 | * in which to lookup the configuration property | |
98 | * @param key A non-<tt>null</tt>, non-empty (trim'd) string representing the name of the property to be | |
99 | * looked up | |
100 | * | |
101 | * @return the String value looked up from the {@link ConfigManager} | |
102 | * | |
103 | * @throws IllegalArgumentException if namespace or key are <tt>null</tt> or empty (trim'd) strings | |
104 | * @throws PersistenceConfigurationException | |
105 | * in case the given namespace is unknown, the property lookup fails or returns | |
106 | * <tt>null</tt>, or an empty (trim'd) string | |
107 | */ | |
108 | public static String lookupValidStringFromConfigManager(final String namespace, final String key) throws | |
109 | PersistenceConfigurationException { | |
110 | // arg checking done in internalLookupStringFromConfigManager | |
111 | final String value; | |
112 | try { | |
113 | 1012 | value = internalLookupStringFromConfigManager(namespace, key); |
114 | 5 | } catch (UnknownNamespaceException e) { |
115 | 5 | throw new PersistenceConfigurationException( |
116 | "The given namespace [" + namespace + "] did not exist in ConfigManager.", | |
117 | e); | |
118 | 1003 | } |
119 | 1003 | if (value == null) { |
120 | 8 | throw new PersistenceConfigurationException( |
121 | "The configuration value for the property [" + key + "] in namespace [" + namespace + "] was null."); | |
122 | } | |
123 | 995 | if (value.trim().length() == 0) { |
124 | 6 | throw new PersistenceConfigurationException("The configuration value for the property [" + key |
125 | + "] in namespace [" + namespace + "] was an empty String."); | |
126 | } | |
127 | 989 | return value; |
128 | } | |
129 | ||
130 | /** | |
131 | * This method looks up an optional configuration property of type {@link String} from the {@link ConfigManager}. | |
132 | * | |
133 | * @param namespace A non-<tt>null</tt>, non-empty (trim'd) string representing the {@link ConfigManager} namespace | |
134 | * in which to lookup the configuration property | |
135 | * @param key A non-<tt>null</tt>, non-empty (trim'd) string representing the name of the property to be | |
136 | * looked up | |
137 | * | |
138 | * @return the String value looked up from the {@link ConfigManager} or <tt>null</tt> if the value cannot be found, | |
139 | * or was <tt>null</tt> or an empty String | |
140 | * | |
141 | * @throws IllegalArgumentException if namespace or key are <tt>null</tt> or empty (trim'd) strings | |
142 | */ | |
143 | public static String lookupOptionalStringFromConfigManager(final String namespace, final String key) { | |
144 | // arg checking done in internalLookupStringFromConfigManager | |
145 | try { | |
146 | 1270 | final String value = internalLookupStringFromConfigManager(namespace, key); |
147 | 1262 | if (value != null && value.trim().length() == 0) { |
148 | 3 | return null; |
149 | } | |
150 | 1259 | return value; |
151 | 4 | } catch (UnknownNamespaceException e) { |
152 | 4 | return null; |
153 | } | |
154 | } | |
155 | ||
156 | /** | |
157 | * This method serializes the given object. | |
158 | * | |
159 | * @param object the object to be serialized | |
160 | * | |
161 | * @return the serialized form of the given object | |
162 | * | |
163 | * @throws IndexPersistenceException in case the serialization fails | |
164 | * @throws IllegalArgumentException in case the given object is <tt>null</tt> | |
165 | */ | |
166 | public static byte[] serializeObject(final Object object) throws IndexPersistenceException { | |
167 | 99 | if (object == null) { |
168 | 1 | throw new IllegalArgumentException("The parameter named [object] was null."); |
169 | } | |
170 | ||
171 | 98 | final ByteArrayOutputStream baos = new ByteArrayOutputStream(ONE_KILOBYTE); |
172 | try { | |
173 | 98 | final ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos); |
174 | 98 | objectOutputStream.writeObject(object); |
175 | 98 | objectOutputStream.close(); |
176 | 98 | return baos.toByteArray(); |
177 | 0 | } catch (IOException e) { |
178 | 0 | throw new IndexPersistenceException("Unable to serialize the given Object [" + object + "] of type [" |
179 | + object.getClass().getName() + "].", e); | |
180 | } | |
181 | // no closing of streams needed as the underlying | |
182 | // streams are ByteArrayOutputStreams, | |
183 | // which are explicitly declared as not necessary to be closed. | |
184 | } | |
185 | ||
186 | /** | |
187 | * This method deserializes an {@link Object} from the given bytes. | |
188 | * | |
189 | * @param bytes the bytes to be deserialized into an {@link Object} | |
190 | * | |
191 | * @return the deserialized {@link Object} | |
192 | * | |
193 | * @throws IndexPersistenceException in case the deserialization fails | |
194 | * @throws IllegalArgumentException in case the given bytes is <tt>null</tt> | |
195 | */ | |
196 | public static Object deSerializeObject(final byte[] bytes) throws IndexPersistenceException { | |
197 | 87 | if (bytes == null) { |
198 | 1 | throw new IllegalArgumentException("The parameter named [bytes] was null."); |
199 | } | |
200 | 86 | final InputStream in = new ByteArrayInputStream(bytes); |
201 | ||
202 | try { | |
203 | 86 | final ObjectInputStream objectInputStream = new ObjectInputStream(in); |
204 | 86 | return objectInputStream.readObject(); |
205 | // no closing of streams needed as the underlying | |
206 | // streams are ByteArrayOutputStreams and ByteArrayInputStreams, | |
207 | // which are explicitly declared as not necessary to be closed. | |
208 | 0 | } catch (Exception e) { |
209 | // catch of Exception is normally discouraged by the TC coding style, but | |
210 | // as a lot of Exceptions can arise from a deserialization | |
211 | // all Exceptions are caught in | |
212 | // this single catch clause, as no specialized handling | |
213 | // of different exception types is possible. | |
214 | 0 | throw new IndexPersistenceException("Error while deserializing Object from byte[].", e); |
215 | } | |
216 | } | |
217 | ||
218 | /** | |
219 | * This method does create a unique String identifier from the given WordSourceId by calculating the MD5 hash sum of | |
220 | * the binary representation of the given WordSourceId and returning the Hex-encoding String of that hash code. | |
221 | * | |
222 | * @param sourceId the WordSourceId to create the id string for | |
223 | * | |
224 | * @return the id string of the given WordSourceId | |
225 | * | |
226 | * @throws IndexPersistenceException in case the creation of the id string fails | |
227 | * @throws IllegalArgumentException in case the given sourceId is <tt>null</tt> | |
228 | */ | |
229 | public static String createIdString(final WordSourceId sourceId) throws IndexPersistenceException { | |
230 | 385 | if (sourceId == null) { |
231 | 1 | throw new IllegalArgumentException("The parameter named [sourceId] was null."); |
232 | } | |
233 | ||
234 | // serialize the complete state of the wordSourceId to a byte[] | |
235 | 384 | final ByteArrayOutputStream baos = new ByteArrayOutputStream(ONE_KILOBYTE); |
236 | final byte[] bytes; | |
237 | try { | |
238 | 384 | final ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos); |
239 | 384 | objectOutputStream.writeObject(sourceId.getSourceIdentity()); |
240 | 384 | objectOutputStream.writeObject(sourceId.getSourceClassName()); |
241 | 384 | objectOutputStream.writeObject(sourceId.getSourceLocale()); |
242 | 384 | objectOutputStream.writeObject(sourceId.getDelimiters()); |
243 | 384 | objectOutputStream.close(); |
244 | 384 | bytes = baos.toByteArray(); |
245 | 0 | } catch (IOException e) { |
246 | 0 | throw new IndexPersistenceException( |
247 | "Unable to serialize the WordSourceId [" + sourceId + "] for digesting.", e); | |
248 | 384 | } |
249 | ||
250 | // Create an MD5 message digest | |
251 | try { | |
252 | // Create an MD5 message digest | |
253 | 384 | final MessageDigest msgDigest = MessageDigest.getInstance("MD5"); |
254 | 384 | msgDigest.update(bytes); |
255 | 384 | final byte[] digest = msgDigest.digest(); |
256 | ||
257 | //now do a HEX encoding and return the String | |
258 | 384 | final char[] hex = new char[digest.length * 2]; //we need 2 characters per byte |
259 | 6528 | for (int i = 0; i < digest.length; i++) { |
260 | 6144 | final int b = digest[i] & ONE_BYTE_MASK; |
261 | 6144 | hex[2 * i] = HEX_DIGITS[b / NIBBLE_MASK]; |
262 | 6144 | hex[2 * i + 1] = HEX_DIGITS[b % NIBBLE_MASK]; |
263 | } | |
264 | 384 | return new String(hex); |
265 | 0 | } catch (NoSuchAlgorithmException e) { |
266 | 0 | throw new IndexPersistenceException("Unable to digest the serialized WordSourceId [" + sourceId + "].", e); |
267 | } | |
268 | } | |
269 | ||
270 | /** | |
271 | * This method looks up a configuration property of type {@link String} from the {@link ConfigManager}. | |
272 | * | |
273 | * @param namespace A non-<tt>null</tt>, non-empty (trim'd) string representing the {@link ConfigManager} namespace | |
274 | * in which to lookup the configuration property | |
275 | * @param key A non-<tt>null</tt>, non-empty (trim'd) string representing the name of the property to be | |
276 | * looked up | |
277 | * | |
278 | * @return the String value looked up from the {@link ConfigManager} or <tt>null</tt> if the value cannot be found | |
279 | * | |
280 | * @throws IllegalArgumentException if namespace or key are <tt>null</tt> or empty (trim'd) strings | |
281 | * @throws UnknownNamespaceException in case the given namespace does not exist in ConfigManager | |
282 | */ | |
283 | private static String internalLookupStringFromConfigManager(final String namespace, final String key) throws | |
284 | UnknownNamespaceException { | |
285 | 2282 | if (namespace == null) { |
286 | 2 | throw new IllegalArgumentException("The parameter named [namespace] was null."); |
287 | } | |
288 | 2280 | if (key == null) { |
289 | 2 | throw new IllegalArgumentException("The parameter named [key] was null."); |
290 | } | |
291 | 2278 | if (namespace.trim().length() == 0) { |
292 | 2 | throw new IllegalArgumentException("The parameter named [namespace] was an empty String."); |
293 | } | |
294 | 2276 | if (key.trim().length() == 0) { |
295 | 2 | throw new IllegalArgumentException("The parameter named [key] was an empty String."); |
296 | } | |
297 | ||
298 | 2274 | return ConfigManager.getInstance().getString(namespace, key); |
299 | } | |
300 | ||
301 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |