1
2 package org.galagosearch.tupleflow;
3
4 import java.io.BufferedReader;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.FileReader;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.InputStreamReader;
12 import java.io.OutputStream;
13 import java.io.UnsupportedEncodingException;
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import java.net.ServerSocket;
17 import java.security.MessageDigest;
18 import java.util.ArrayList;
19 import java.util.HashSet;
20 import java.util.logging.Logger;
21 import org.galagosearch.tupleflow.execution.Step;
22
23 /***
24 * Lots of static methods here that have broad use.
25 *
26 * @author trevor
27 */
28 public class Utility {
29 /***
30 * Builds a simple Sorter step that can be added to a TupleFlow stage.
31 *
32 * @param sortOrder An order object representing how and what to sort.
33 * @return a Step object that can be added to a TupleFlow Stage.
34 */
35 public static Step getSorter(Order sortOrder) {
36 Parameters p = new Parameters();
37 p.add("class", sortOrder.getOrderedClass().getName());
38 p.add("order", Utility.join(sortOrder.getOrderSpec()));
39 return new Step(Sorter.class, p);
40 }
41
42 /***
43 * Finds a free port to listen on. Useful for starting up internal web servers.
44 * (copied from chaoticjava.com)
45 */
46 public static int getFreePort() throws IOException {
47 ServerSocket server = new ServerSocket(0);
48 int port = server.getLocalPort();
49 server.close();
50 return port;
51 }
52
53 public static boolean isInteger(String s) {
54 try {
55 Integer.parseInt(s);
56 return true;
57 } catch (Exception e) {
58 return false;
59 }
60 }
61
62 public static String wrap(String t) {
63 int start = 0;
64 StringBuilder result = new StringBuilder();
65
66 while (t.length() > start + 50) {
67 int end = t.indexOf(" ", start + 50);
68
69 if (end < 0) {
70 break;
71 }
72 result.append(t, start, end);
73 result.append('\n');
74 start = end + 1;
75 }
76
77 result.append(t.substring(start));
78 return result.toString();
79 }
80
81 public static String escape(String raw) {
82 StringBuilder builder = new StringBuilder();
83
84 for (int i = 0; i < raw.length(); i++) {
85 char c = raw.charAt(i);
86
87 if (c == '"') {
88 builder.append(""");
89 } else if (c == '&') {
90 builder.append("&");
91 } else if (c == '<') {
92 builder.append(">");
93 } else if (c == '>') {
94 builder.append("<");
95 } else if (c <= 127) {
96 builder.append(c);
97 } else {
98 int unsigned = ((int) c) & 0xFFFF;
99
100 builder.append("&#");
101 builder.append(unsigned);
102 builder.append(";");
103 }
104 }
105
106 return builder.toString();
107 }
108
109 public static String strip(String source, String suffix) {
110 if (source.endsWith(suffix)) {
111 return source.substring(0, source.length() - suffix.length());
112 }
113
114 return null;
115 }
116
117 public static String makeString(byte[] word) {
118 try {
119 return new String(word, "UTF-8");
120 } catch (UnsupportedEncodingException e) {
121 throw new RuntimeException("UTF-8 is not supported by your Java Virtual Machine.");
122 }
123 }
124
125 public static byte[] makeBytes(String word) {
126 try {
127 return word.getBytes("UTF-8");
128 } catch (UnsupportedEncodingException e) {
129 throw new RuntimeException("UTF-8 is not supported by your Java Virtual Machine.");
130 }
131 }
132
133 /***
134 * For an array master, returns
135 * an array containing the last master.length-index elements.
136 */
137 public static String[] subarray(String[] master, int index) {
138 if (master.length <= index) {
139 return new String[0];
140 } else {
141 String[] sub = new String[master.length - index];
142 System.arraycopy(master, index, sub, 0, sub.length);
143 return sub;
144 }
145 }
146
147 /***
148 * Returns a string containing all the elements of args, space delimited.
149 */
150 public static String join(String[] args, String delimiter) {
151 String output = "";
152 StringBuilder builder = new StringBuilder();
153
154 for (String arg : args) {
155 if (builder.length() > 0) {
156 builder.append(delimiter);
157 }
158 builder.append(arg);
159 }
160
161 return builder.toString();
162 }
163
164 public static String join(String[] args) {
165 return join(args, " ");
166 }
167
168 public static String caps(String input) {
169 if (input.length() == 0) {
170 return input;
171 }
172 char first = Character.toUpperCase(input.charAt(0));
173 return "" + first + input.substring(1);
174 }
175
176 public static String plural(String input) {
177 return input + "s";
178 }
179
180 public static int compare(int one, int two) {
181 return one - two;
182 }
183
184 public static int compare(long one, long two) {
185 long result = one - two;
186
187 if (result > 0) {
188 return 1;
189 }
190 if (result < 0) {
191 return -1;
192 }
193 return 0;
194 }
195
196 public static int compare(double one, double two) {
197 double result = one - two;
198
199 if (result > 0) {
200 return 1;
201 }
202 if (result < 0) {
203 return -1;
204 }
205 return 0;
206 }
207
208 public static int compare(float one, float two) {
209 float result = one - two;
210
211 if (result > 0) {
212 return 1;
213 }
214 if (result < 0) {
215 return -1;
216 }
217 return 0;
218 }
219
220 public static int compare(String one, String two) {
221 return one.compareTo(two);
222 }
223
224 public static int compare(byte[] one, byte[] two) {
225 int sharedLength = Math.min(one.length, two.length);
226
227 for (int i = 0; i < sharedLength; i++) {
228 int a = ((int) one[i]) & 0xFF;
229 int b = ((int) two[i]) & 0xFF;
230 int result = a - b;
231
232 if (result < 0) {
233 return -1;
234 }
235 if (result > 0) {
236 return 1;
237 }
238 }
239
240 return one.length - two.length;
241 }
242
243 public static int hash(byte b) {
244 return ((int) b) & 0xFF;
245 }
246
247 public static int hash(int i) {
248 return i;
249 }
250
251 public static int hash(long l) {
252 return (int) l;
253 }
254
255 public static int hash(double d) {
256 return (int) (d * 100000);
257 }
258
259 public static int hash(float f) {
260 return (int) (f * 100000);
261 }
262
263 public static int hash(String s) {
264 return s.hashCode();
265 }
266
267 public static int hash(byte[] b) {
268 int h = 0;
269 for (int i = 0; i < b.length; i++) {
270 h += 7 * h + b[i];
271 }
272 return h;
273 }
274
275 public static void deleteDirectory(File directory) throws IOException {
276 for (File sub : directory.listFiles()) {
277 if (sub.isDirectory()) {
278 deleteDirectory(sub);
279 } else {
280 sub.delete();
281 }
282 }
283
284 directory.delete();
285 }
286
287 public static File createTemporary() throws IOException {
288 return createTemporary(1024 * 1024 * 1024);
289 }
290
291 public static long getUnixFreeSpace(String pathname) throws IOException {
292 try {
293
294 String[] command = {"df", "-Pk", pathname};
295 Process process = Runtime.getRuntime().exec(command);
296 InputStream procOutput = process.getInputStream();
297 BufferedReader reader = new BufferedReader(new InputStreamReader(procOutput));
298
299
300 reader.readLine();
301 String line = reader.readLine();
302 String[] fields = line.split("//s+");
303 reader.close();
304
305 process.getErrorStream().close();
306 process.getInputStream().close();
307 process.getOutputStream().close();
308 process.waitFor();
309
310 long freeSpace = Long.parseLong(fields[3]) * 1024;
311 return freeSpace;
312 } catch (InterruptedException ex) {
313 return 0;
314 }
315 }
316
317 public static long getFreeSpace(String pathname) throws IOException {
318 try {
319
320 Method m = File.class.getMethod("getUsableSpace");
321 Long result = (Long) m.invoke(new File(pathname));
322 return (long) result;
323 } catch (Exception e) {
324 try {
325 return getUnixFreeSpace(pathname);
326 } catch(Exception ex) {
327 return 1024*1024*1024;
328 }
329 }
330 }
331
332 public static File createTemporary(long requiredSpace) throws IOException {
333
334 String homeDirectory = System.getProperty("user.home");
335 File prefsFile = new File(homeDirectory + "/" + ".galagotmp");
336 ArrayList<String> roots = new ArrayList<String>();
337 File temporary = null;
338
339 if (prefsFile.exists()) {
340 BufferedReader reader = new BufferedReader(new FileReader(prefsFile));
341 String line;
342
343 while ((line = reader.readLine()) != null) {
344 roots.add(line.trim());
345 }
346
347 reader.close();
348 }
349
350 for (String root : roots) {
351 long freeSpace = getFreeSpace(root);
352
353 if (freeSpace < requiredSpace) {
354 continue;
355 }
356 String logString = String.format("Found %6.3fMB >= %6.3fMB left on %s",
357 freeSpace / 1048576.0, requiredSpace / 1048576.0, root);
358 Logger.getLogger(Utility.class.toString()).info(logString);
359 temporary = File.createTempFile("tupleflow", "", new File(root));
360 break;
361 }
362
363 if (temporary == null) {
364 temporary = File.createTempFile("tupleflow", "");
365 }
366
367 return temporary;
368 }
369
370 /***
371 * Copies the data from file into the stream. Note that this method
372 * does not close the stream (in case you want to put more in it).
373 *
374 * @param file
375 * @param stream
376 * @throws java.io.IOException
377 */
378 public static void copyFileToStream(File file, OutputStream stream) throws IOException {
379 FileInputStream input = new FileInputStream(file);
380 long longLength = file.length();
381 final int fiveMegabytes = 5 * 1024 * 1024;
382
383 while (longLength > 0) {
384 int chunk = (int) Math.min(longLength, fiveMegabytes);
385 byte[] data = new byte[chunk];
386 input.read(data, 0, chunk);
387 stream.write(data, 0, chunk);
388 longLength -= chunk;
389 }
390
391 input.close();
392 }
393
394 /***
395 * Copies the data from the InputStream to a file, then closes both when
396 * finished.
397 *
398 * @param stream
399 * @param file
400 * @throws java.io.IOException
401 */
402 public static void copyStreamToFile(InputStream stream, File file) throws IOException {
403 FileOutputStream output = new FileOutputStream(file);
404 final int oneMegabyte = 1 * 1024 * 1024;
405 byte[] data = new byte[oneMegabyte];
406
407 while (true) {
408 int bytesRead = stream.read(data);
409
410 if (bytesRead < 0) {
411 break;
412 }
413 output.write(data, 0, bytesRead);
414 }
415
416 stream.close();
417 output.close();
418 }
419
420 public static void calculateMessageDigest(File file, MessageDigest instance) throws IOException {
421 FileInputStream input = new FileInputStream(file);
422 final int oneMegabyte = 1024 * 1024;
423 byte[] data = new byte[oneMegabyte];
424
425 while (true) {
426 int bytesRead = input.read(data);
427
428 if (bytesRead < 0) {
429 break;
430 }
431 instance.update(data, 0, bytesRead);
432 }
433
434 input.close();
435 }
436
437 public static HashSet<String> readFileToStringSet(File file) throws IOException {
438 BufferedReader reader = new BufferedReader(new FileReader(file));
439 HashSet<String> set = new HashSet<String>();
440 String line;
441
442 while ((line = reader.readLine()) != null) {
443 set.add(line.trim());
444 }
445
446 reader.close();
447 return set;
448 }
449 }