1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 package org.openoffice.test.common;
23 
24 import java.awt.Toolkit;
25 import java.awt.datatransfer.Clipboard;
26 import java.awt.datatransfer.DataFlavor;
27 import java.awt.datatransfer.StringSelection;
28 import java.awt.datatransfer.Transferable;
29 import java.io.BufferedReader;
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.StringReader;
33 import java.net.InetAddress;
34 import java.net.URL;
35 import java.net.UnknownHostException;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Enumeration;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.StringTokenizer;
42 import java.util.logging.Level;
43 import java.util.logging.Logger;
44 import java.util.zip.ZipEntry;
45 import java.util.zip.ZipInputStream;
46 
47 /**
48  * Utilities related to system
49  *
50  */
51 public class SystemUtil {
52 
53 	private static Logger LOG = Logger.getLogger(SystemUtil.class.getName());
54 
55 	private static Clipboard sysClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
56 
57 	private static final File SCRIPT_TEMP_DIR = Testspace.getFile("bin");
58 
59 	private static String platform = System.getProperty("os.name");
60 
61 	private static String osName = System.getProperty("os.name");
62 
63 	private static String osVersion  = System.getProperty("os.version");
64 
65 	private static String osArch = System.getProperty("os.arch");
66 
67 	static {
68 		if (isLinux()) {
69 			StringBuffer output = new StringBuffer();
70 			if (exec(new String[]{"lsb_release", "-is"}, output) == 0)
71 				osName = output.toString().trim();
72 			output.setLength(0);
73 			if (exec(new String[]{"lsb_release", "-rs"}, output) == 0)
74 				osVersion = output.toString().trim();
75 		}
76 	}
77 
78 	/**
79 	 * Play beep sound! The method doesn't work, if the code is executed on
80 	 * Eclipse IDE.
81 	 *
82 	 */
beep()83 	public static void beep() {
84 		System.out.print("\007\007\007");
85 		System.out.flush();
86 	}
87 
isWindows()88 	public static boolean isWindows() {
89 		return platform.startsWith("Windows");
90 	}
91 
isLinux()92 	public static boolean isLinux() {
93 		return platform.startsWith("Linux");
94 	}
95 
isMac()96 	public static boolean isMac() {
97 		return platform.startsWith("Mac");
98 	}
99 
isBSD()100 	public static boolean isBSD() {
101 		return platform.endsWith("BSD");
102 	}
103 
getOSName()104 	public static String getOSName() {
105 		return osName;
106 	}
107 
getOSVersion()108 	public static String getOSVersion() {
109 		return osVersion;
110 	}
111 
getOSArch()112 	public static String getOSArch() {
113 		return osArch;
114 	}
115 
116 	/**
117 	 * Set the contents of the clipboard to the provided text
118 	 */
setClipboardText(String s)119 	public static void setClipboardText(String s) {
120 		StringSelection ss = new StringSelection(s);
121 
122 		// if (OS.get() == OS.MACOSX) {
123 		// // workaround MAC OS X has a bug. After setting a text into
124 		// clipboard, the java program will not
125 		// // receive the data written by other applications.
126 		// File file = null;
127 		// try {
128 		// file = File.createTempFile("SystemUtil", "SystemUtil");
129 		// FileUtil.writeStringToFile(file.getAbsolutePath(), s);
130 		// if (exec("pbcopy < \""+ file.getAbsolutePath() + "\"", false) == 0)
131 		// return;
132 		// } catch (IOException e) {
133 		// // TODO Auto-generated catch block
134 		// e.printStackTrace();
135 		// } finally {
136 		// if (file != null)
137 		// file.delete();
138 		// }
139 		//
140 		// }
141 		//
142 		sysClipboard.setContents(ss, ss);
143 	}
144 
145 	/**
146 	 * Get plain text from clipboard
147 	 *
148 	 * @return
149 	 */
getClipboardText()150 	public static String getClipboardText() {
151 		Transferable contents = getTransferable();
152 		if (contents == null || !contents.isDataFlavorSupported(DataFlavor.stringFlavor))
153 			return "";
154 		try {
155 			return (String) contents.getTransferData(DataFlavor.stringFlavor);
156 		} catch (Exception ex) {
157 			return "";
158 		}
159 	}
160 
getTransferable()161 	private static Transferable getTransferable() {
162 		// To avoid IllegalStateException, we try 25 times to access clipboard.
163 		for (int i = 0; i < 25; i++) {
164 			try {
165 				return sysClipboard.getContents(null);
166 			} catch (IllegalStateException e) {
167 				try {
168 					Thread.sleep(200);
169 				} catch (InterruptedException e1) {
170 				}
171 			}
172 		}
173 		throw new RuntimeException("System Clipboard is not ready");
174 	}
175 
176 	/**
177 	 * Execute a script and waiting it for finishing
178 	 *
179 	 * @param content
180 	 * @return
181 	 */
execScript(String content)182 	public static int execScript(String content) {
183 		StringBuffer output = new StringBuffer();
184 		int code = execScript(content, output, output);
185 		LOG.info(content + "\n" + "Exit Code: " + code + "\n" + output);
186 		return code;
187 	}
188 
189 	/**
190 	 * Execute a script and waiting it for finishing
191 	 * @param content
192 	 * @param output
193 	 * @param error
194 	 * @return
195 	 */
execScript(String content, StringBuffer output, StringBuffer error)196 	public static int execScript(String content, StringBuffer output, StringBuffer error) {
197 		File file = null;
198 		try {
199 			file = FileUtil.getUniqueFile(SCRIPT_TEMP_DIR, "tempscript", ".bat");
200 			FileUtil.writeStringToFile(file.getAbsolutePath(), content);
201 			String[] cmd;
202 			if (isWindows())
203 				cmd = new String[] { file.getAbsolutePath() };
204 			else
205 				cmd = new String[] { "sh", file.getAbsolutePath() };
206 			return exec(cmd, null, null, output, error);
207 		} catch (Exception e) {
208 			return -1;
209 		} finally {
210 			if (file != null && !file.delete())
211 				file.deleteOnExit();
212 		}
213 	}
214 
215 	/**
216 	 * Start a background process
217 	 * @param cmd
218 	 * @param env
219 	 * @param dir
220 	 * @param output
221 	 * @param error
222 	 * @return
223 	 */
backgroundExec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error)224 	public static Process backgroundExec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error) {
225 		try {
226 			Process process = Runtime.getRuntime().exec(cmd, env, dir);
227 			StreamPump inputPump = new StreamPump(output, process.getInputStream());
228 			StreamPump errorPump = new StreamPump(error, process.getErrorStream());
229 			inputPump.start();
230 			errorPump.start();
231 			return process;
232 		} catch (Exception e) {
233 			return null;
234 		}
235 	}
236 
237 	/**
238 	 * Execute the command and wait for its finishing
239 	 * @param cmd
240 	 * @param env
241 	 * @param dir
242 	 * @param output
243 	 * @param error
244 	 * @return
245 	 */
exec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error)246 	public static int exec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error) {
247 		Process process = null;
248 		try {
249 			LOG.log(Level.FINE,  "exec: " + Arrays.toString(cmd));
250 			process = Runtime.getRuntime().exec(cmd, env, dir);
251 		} catch (Exception e) {
252 			e.printStackTrace();
253 			return -1;
254 		}
255 
256 		StreamPump inputPump = new StreamPump(output, process.getInputStream());
257 		StreamPump errorPump = new StreamPump(error, process.getErrorStream());
258 		inputPump.start();
259 		errorPump.start();
260 
261 		try {
262 			int code = process.waitFor();
263 			inputPump.join();
264 			errorPump.join();
265 			return code;
266 		} catch (InterruptedException e) {
267 			return -2;
268 		}
269 	}
270 
exec(String[] cmd, StringBuffer output)271 	public static int exec(String[] cmd, StringBuffer output) {
272 		return exec(cmd, null, null, output, output);
273 	}
274 
275 	/**
276 	 * Make the current thread sleep some seconds.
277 	 *
278 	 * @param second
279 	 */
sleep(double second)280 	public static void sleep(double second) {
281 		try {
282 			if (second > 0)
283 				Thread.sleep((long) (second * 1000));
284 		} catch (InterruptedException e) {
285 		}
286 	}
287 
288 	/**
289 	 * Get Information of running processes
290 	 *
291 	 */
getProcesses()292 	public static List<HashMap<String, Object>> getProcesses() {
293 		List<HashMap<String, Object>> ret = new ArrayList<HashMap<String, Object>>();
294 		try {
295 			StringBuffer output = new StringBuffer();
296 			if (isWindows()) {
297 				File file = new File(SCRIPT_TEMP_DIR, "ps.vbs");
298 //				if (!file.exists()) {
299 					String contents = "Set wmi=GetObject(\"Winmgmts:\")\n\r"
300 							+ "Set ps = wmi.ExecQuery(\"Select * from Win32_Process\")\n\r"
301 							+ "WScript.Echo \"PID COMMAND\" \n\r"
302 							+ "For Each p in ps\n\r"
303 							+ "WScript.Echo p.ProcessId & \" \" & p.CommandLine\n\r"
304 							+ "Next";
305 					FileUtil.writeStringToFile(file.getAbsolutePath(), contents);
306 //				}
307 				exec(new String[] { "cscript", "//Nologo", file.getAbsolutePath()}, null, null, output, output);
308 			} else if (isBSD()) {
309 				exec(new String[] {"ps", "-wwo", "pid,command"}, null, null, output, output);
310 			} else {
311 				exec(new String[] {"ps", "-eo", "pid,command"}, null, null, output, output);
312 			}
313 
314 			BufferedReader reader = new BufferedReader(new StringReader(output.toString()));
315 			String line = null;
316 			reader.readLine();
317 			while ((line = reader.readLine()) != null) {
318 				HashMap<String, Object> p = new HashMap<String, Object>();
319 				StringTokenizer tokenizer = new StringTokenizer(line, " ", true);
320 				StringBuffer last = new StringBuffer();
321 				int col = 0;
322 				while (tokenizer.hasMoreTokens()) {
323 					String token = tokenizer.nextToken();
324 					switch (col) {
325 					case 0:
326 						if (!" ".equals(token)) {
327 							//
328 							p.put("pid", token);
329 							col++;
330 						}
331 						break;
332 					default:
333 						last.append(token);
334 						break;
335 					}
336 				}
337 
338 				p.put("command", last.toString().trim());
339 				ret.add(p);
340 			}
341 		} catch (IOException e) {
342 
343 		}
344 
345 		return ret;
346 	}
347 
killProcess(String pattern)348 	public static void killProcess(String pattern) {
349 		List<HashMap<String, Object>> processes = SystemUtil.getProcesses();
350 		for (HashMap<String, Object> p : processes) {
351 			String command = (String) p.get("command");
352 			String pid = (String) p.get("pid");
353 			if (command != null && command.matches(pattern)) {
354 				if (isWindows()) {
355 					exec(new String[] { "taskkill", "/F", "/PID", pid }, null, null, null, null);
356 				} else {
357 					exec(new String[] { "kill", "-9", pid }, null, null, null, null);
358 				}
359 			}
360 		}
361 	}
362 
hasProcess(String pattern)363 	public static boolean hasProcess(String pattern) {
364 		return findProcess(pattern) != null;
365 	}
366 
findProcess(String pattern)367 	public static HashMap<String, Object> findProcess(String pattern) {
368 		List<HashMap<String, Object>> processes = SystemUtil.getProcesses();
369 		for (HashMap<String, Object> p : processes) {
370 			String command = (String) p.get("command");
371 			if (command != null && command.matches(pattern)) {
372 				return p;
373 			}
374 		}
375 
376 		return null;
377 	}
378 
findProcesses(String pattern)379 	public static List<HashMap<String, Object>> findProcesses(String pattern) {
380 		List<HashMap<String, Object>> result = new ArrayList<HashMap<String, Object>>();
381 		List<HashMap<String, Object>> processes = SystemUtil.getProcesses();
382 		for (HashMap<String, Object> p : processes) {
383 			String command = (String) p.get("command");
384 			if (command != null && command.matches(pattern)) {
385 				result.add(p);
386 			}
387 		}
388 
389 		return result;
390 	}
391 
392 	/**
393 	 * Get Information of running processes
394 	 *
395 	 */
getProcessPerfData(String processId)396 	public static HashMap<String, Object> getProcessPerfData(String processId) {
397 		try {
398 			StringBuffer output = new StringBuffer();
399 			if (isWindows()) {
400 				File file = new File(SCRIPT_TEMP_DIR, "pps.vbs");
401 				String contents = "Set wmi=GetObject(\"Winmgmts:\")\n\r"
402 						+ "Set pps = wmi.ExecQuery(\"Select * from Win32_PerfFormattedData_PerfProc_Process Where IDProcess='" + processId+"'\")\n\r"
403 						+ "WScript.Echo \"pcpu PrivateBytes WorkingSet HandleCount\" \n\r"
404 						+ "For Each pp in pps \n\r"
405 						+ "WScript.Echo pp.PercentProcessorTime & \" \" & Round(pp.PrivateBytes/1024) & \" \" & Round(pp.WorkingSet/1024) & \" \" & pp.HandleCount \n\r"
406 						+ "Next";
407 //				String contents = "var wmi = GetObject(\"Winmgmts:\");\n"
408 //						+ "var pps = new Enumerator(wmi.ExecQuery(\"Select * from Win32_PerfFormattedData_PerfProc_Process Where IDProcess='" + processId+"'\"));\n"
409 //						+ "WScript.Echo(\"pcpu rss\");\n"
410 //						+ "for ( ; !pps.atEnd(); pps.moveNext()) {\n"
411 //						+ "var pp = pps.item();\n"
412 //						+ "WScript.Echo(pp.PercentProcessorTime + \" \" + (pp.WorkingSet/1024));\n"
413 //						+ "}";
414 				FileUtil.writeStringToFile(file.getAbsolutePath(), contents);
415 				exec(new String[] { "cscript", "//Nologo", file.getAbsolutePath()}, null, null, output, output);
416 			} else {
417 				exec(new String[] {"ps", "-p", processId ,"-o", "pcpu,vsz,rss,tty"}, null, null, output, output);
418 			}
419 			BufferedReader reader = new BufferedReader(new StringReader(output.toString()));
420 			String line = null;
421 			reader.readLine();
422 			if ((line = reader.readLine()) != null) {
423 				HashMap<String, Object> p = new HashMap<String, Object>();
424 				StringTokenizer tokenizer = new StringTokenizer(line, " ", true);
425 				int col = 0;
426 				while (tokenizer.hasMoreTokens()) {
427 					String token = tokenizer.nextToken();
428 					switch (col) {
429 					case 0:
430 						if (!" ".equals(token)) {
431 							//
432 							p.put("pcpu", Double.parseDouble(token));
433 							col++;
434 						}
435 						break;
436 					case 1:
437 						if (!" ".equals(token)) {
438 							//
439 							p.put("vsz", Long.parseLong(token));
440 							col++;
441 						}
442 						break;
443 					case 2:
444 						if (!" ".equals(token)) {
445 							//
446 							p.put("rss", Long.parseLong(token));
447 							col++;
448 						}
449 						break;
450 					case 3:
451 						if (!" ".equals(token)) {
452 							//
453 							try {
454 								p.put("handles", Long.parseLong(token));
455 							} catch (Exception e) {
456 								p.put("handles", 0l);
457 							}
458 
459 							col++;
460 						}
461 						break;
462 					}
463 				}
464 				return p;
465 			}
466 		} catch (IOException e) {
467 
468 		}
469 
470 		return null;
471 	}
472 
473 	/**
474 	 * parse a string to arguments array.
475 	 *
476 	 * @param line
477 	 * @return
478 	 */
parseCommandLine(String line)479 	public static String[] parseCommandLine(String line) {
480 		ArrayList<String> arguments = new ArrayList<String>();
481 		StringTokenizer tokenizer = new StringTokenizer(line, "\"\' ", true);
482 		int state = 0;
483 		StringBuffer current = new StringBuffer();
484 		while (tokenizer.hasMoreTokens()) {
485 			String token = tokenizer.nextToken();
486 			switch (state) {
487 			case 1:
488 				if ("\'".equals(token)) {
489 					state = 3;
490 				} else {
491 					current.append(token);
492 				}
493 				break;
494 			case 2:
495 				if ("\"".equals(token)) {
496 					state = 3;
497 				} else {
498 					current.append(token);
499 				}
500 				break;
501 			default:
502 				if ("\'".equals(token)) {
503 					state = 1;
504 				} else if ("\"".equals(token)) {
505 					state = 2;
506 				} else if (" ".equals(token)) {
507 					if (current.length() > 0) {
508 						arguments.add(current.toString());
509 						current = new StringBuffer();
510 					}
511 				} else {
512 					current.append(token);
513 				}
514 				break;
515 			}
516 		}
517 		if (current.length() > 0)
518 			arguments.add(current.toString());
519 		return arguments.toArray(new String[arguments.size()]);
520 	}
521 
522 	/**
523 	 * Get local host's IP
524 	 * @return
525 	 */
getIPAddress()526 	public static String getIPAddress() {
527 		try {
528 			return InetAddress.getLocalHost().getHostAddress().toString();
529 		} catch (UnknownHostException e) {
530 			return null;
531 		}
532 	}
533 
534 	/**
535 	 * Get local host name
536 	 * @return
537 	 */
getHostName()538 	public static String getHostName() {
539 		try {
540 			return InetAddress.getLocalHost().getHostName();
541 		} catch (UnknownHostException e) {
542 			return null;
543 		}
544 
545 	}
546 
getClassesInPackage(String packageName)547 	public static List<String> getClassesInPackage(String packageName) {
548 		ArrayList<String> classes = new ArrayList<String>();
549 		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
550 		String path = packageName.replace('.', '/');
551 		try {
552 			Enumeration<URL> urls = classLoader.getResources(path);
553 			while (urls.hasMoreElements()) {
554 				URL url = urls.nextElement();
555 				if ("file".equals(url.getProtocol())) {
556 					findClasses(packageName, new File(url.toURI()), classes);
557 				} else if ("jar".equals(url.getProtocol())) {
558 					String urlStr = url.toString();
559 					int i = urlStr.indexOf('!');
560 					if (i > 0)
561 						findClasses(packageName, new URL(urlStr.substring(4, i)), classes);
562 				}
563 			}
564 		} catch (Exception e) {
565 			e.printStackTrace();
566 		}
567 //		TreeSet classes = new TreeSet();
568 //		for (String directory : dirs) {
569 //			classes.addAll(findClasses(directory, packageName));
570 //		}
571 //		ArrayList classList = new ArrayList();
572 //		for (String clazz : classes) {
573 //			classList.add(Class.forName(clazz));
574 //		}
575 //		return classList;
576 		return classes;
577 	}
findClasses(String packageName, File dir, List<String> classes)578 	private static void findClasses(String packageName, File dir, List<String> classes) {
579 		if (!dir.isDirectory())
580 			return;
581 		File[] files = dir.listFiles();
582 		for (File file : files) {
583 			String name = file.getName();
584 			if (file.isDirectory()) {
585 				findClasses(packageName + '.'+ name, file, classes);
586 			}  else if (name.endsWith(".class")) {
587 				String className = packageName + '.' + name.substring(0, name.length() - 6);
588 				classes.add(className);
589 			}
590 		}
591 	}
592 
593 
findClasses(String packageName, URL jar, List<String> classes)594 	private static void findClasses(String packageName, URL jar, List<String> classes) {
595 		try {
596 			ZipInputStream zip = new ZipInputStream(jar.openStream());
597 			ZipEntry entry;
598 			while ((entry = zip.getNextEntry()) != null) {
599 				String name = entry.getName();
600 				if (name.endsWith(".class")) {
601 					name = name.replace('/', '.').substring(0, name.length() - 6);
602 					if (name.startsWith(packageName)) {
603 						classes.add(name);
604 					}
605 				}
606 			}
607 
608 		} catch (Exception e) {
609 
610 		}
611 	}
612 }
613