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 
getOSName()100 	public static String getOSName() {
101 		return osName;
102 	}
103 
getOSVersion()104 	public static String getOSVersion() {
105 		return osVersion;
106 	}
107 
getOSArch()108 	public static String getOSArch() {
109 		return osArch;
110 	}
111 
112 	/**
113 	 * Set the contents of the clipboard to the provided text
114 	 */
setClipboardText(String s)115 	public static void setClipboardText(String s) {
116 		StringSelection ss = new StringSelection(s);
117 
118 		// if (OS.get() == OS.MACOSX) {
119 		// // workaround MAC OS X has a bug. After setting a text into
120 		// clipboard, the java program will not
121 		// // receive the data written by other apllications.
122 		// File file = null;
123 		// try {
124 		// file = File.createTempFile("SystemUtil", "SystemUtil");
125 		// FileUtil.writeStringToFile(file.getAbsolutePath(), s);
126 		// if (exec("pbcopy < \""+ file.getAbsolutePath() + "\"", false) == 0)
127 		// return;
128 		// } catch (IOException e) {
129 		// // TODO Auto-generated catch block
130 		// e.printStackTrace();
131 		// } finally {
132 		// if (file != null)
133 		// file.delete();
134 		// }
135 		//
136 		// }
137 		//
138 		sysClipboard.setContents(ss, ss);
139 	}
140 
141 	/**
142 	 * Get plain text from clipboard
143 	 *
144 	 * @return
145 	 */
getClipboardText()146 	public static String getClipboardText() {
147 		Transferable contents = getTransferable();
148 		if (contents == null || !contents.isDataFlavorSupported(DataFlavor.stringFlavor))
149 			return "";
150 		try {
151 			return (String) contents.getTransferData(DataFlavor.stringFlavor);
152 		} catch (Exception ex) {
153 			return "";
154 		}
155 	}
156 
getTransferable()157 	private static Transferable getTransferable() {
158 		// To avoid IllegalStateException, we try 25 times to access clipboard.
159 		for (int i = 0; i < 25; i++) {
160 			try {
161 				return sysClipboard.getContents(null);
162 			} catch (IllegalStateException e) {
163 				try {
164 					Thread.sleep(200);
165 				} catch (InterruptedException e1) {
166 				}
167 			}
168 		}
169 		throw new RuntimeException("System Clipboard is not ready");
170 	}
171 
172 	/**
173 	 * Execute a script and waiting it for finishing
174 	 *
175 	 * @param content
176 	 * @return
177 	 */
execScript(String content)178 	public static int execScript(String content) {
179 		StringBuffer output = new StringBuffer();
180 		int code = execScript(content, output, output);
181 		LOG.info(content + "\n" + "Exit Code: " + code + "\n" + output);
182 		return code;
183 	}
184 
185 	/**
186 	 * Execute a script and waiting it for finishing
187 	 * @param content
188 	 * @param output
189 	 * @param error
190 	 * @return
191 	 */
execScript(String content, StringBuffer output, StringBuffer error)192 	public static int execScript(String content, StringBuffer output, StringBuffer error) {
193 		File file = null;
194 		try {
195 			file = FileUtil.getUniqueFile(SCRIPT_TEMP_DIR, "tempscript", ".bat");
196 			FileUtil.writeStringToFile(file.getAbsolutePath(), content);
197 			String[] cmd;
198 			if (isWindows())
199 				cmd = new String[] { file.getAbsolutePath() };
200 			else
201 				cmd = new String[] { "sh", file.getAbsolutePath() };
202 			return exec(cmd, null, null, output, error);
203 		} catch (Exception e) {
204 			return -1;
205 		} finally {
206 			if (file != null && !file.delete())
207 				file.deleteOnExit();
208 		}
209 	}
210 
211 	/**
212 	 * Start a background process
213 	 * @param cmd
214 	 * @param env
215 	 * @param dir
216 	 * @param output
217 	 * @param error
218 	 * @return
219 	 */
backgroundExec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error)220 	public static Process backgroundExec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error) {
221 		try {
222 			Process process = Runtime.getRuntime().exec(cmd, env, dir);
223 			StreamPump inputPump = new StreamPump(output, process.getInputStream());
224 			StreamPump errorPump = new StreamPump(error, process.getErrorStream());
225 			inputPump.start();
226 			errorPump.start();
227 			return process;
228 		} catch (Exception e) {
229 			return null;
230 		}
231 	}
232 
233 	/**
234 	 * Execute the command and wait for its finishing
235 	 * @param cmd
236 	 * @param env
237 	 * @param dir
238 	 * @param output
239 	 * @param error
240 	 * @return
241 	 */
exec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error)242 	public static int exec(String[] cmd, String[] env, File dir, StringBuffer output, StringBuffer error) {
243 		Process process = null;
244 		try {
245 			LOG.log(Level.FINE,  "exec: " + Arrays.toString(cmd));
246 			process = Runtime.getRuntime().exec(cmd, env, dir);
247 		} catch (Exception e) {
248 			e.printStackTrace();
249 			return -1;
250 		}
251 
252 		StreamPump inputPump = new StreamPump(output, process.getInputStream());
253 		StreamPump errorPump = new StreamPump(error, process.getErrorStream());
254 		inputPump.start();
255 		errorPump.start();
256 
257 		try {
258 			int code = process.waitFor();
259 			inputPump.join();
260 			errorPump.join();
261 			return code;
262 		} catch (InterruptedException e) {
263 			return -2;
264 		}
265 	}
266 
exec(String[] cmd, StringBuffer output)267 	public static int exec(String[] cmd, StringBuffer output) {
268 		return exec(cmd, null, null, output, output);
269 	}
270 
271 	/**
272 	 * Make the current thread sleep some seconds.
273 	 *
274 	 * @param second
275 	 */
sleep(double second)276 	public static void sleep(double second) {
277 		try {
278 			if (second > 0)
279 				Thread.sleep((long) (second * 1000));
280 		} catch (InterruptedException e) {
281 		}
282 	}
283 
284 	/**
285 	 * Get Information of running processes
286 	 *
287 	 */
getProcesses()288 	public static List<HashMap<String, Object>> getProcesses() {
289 		List<HashMap<String, Object>> ret = new ArrayList<HashMap<String, Object>>();
290 		try {
291 			StringBuffer output = new StringBuffer();
292 			if (isWindows()) {
293 				File file = new File(SCRIPT_TEMP_DIR, "ps.vbs");
294 //				if (!file.exists()) {
295 					String contents = "Set wmi=GetObject(\"Winmgmts:\")\n\r"
296 							+ "Set ps = wmi.ExecQuery(\"Select * from Win32_Process\")\n\r"
297 							+ "WScript.Echo \"PID COMMAND\" \n\r"
298 							+ "For Each p in ps\n\r"
299 							+ "WScript.Echo p.ProcessId & \" \" & p.CommandLine\n\r"
300 							+ "Next";
301 					FileUtil.writeStringToFile(file.getAbsolutePath(), contents);
302 //				}
303 				exec(new String[] { "cscript", "//Nologo", file.getAbsolutePath()}, null, null, output, output);
304 			} else {
305 				exec(new String[] {"ps", "-eo", "pid,command"}, null, null, output, output);
306 			}
307 
308 			BufferedReader reader = new BufferedReader(new StringReader(output.toString()));
309 			String line = null;
310 			reader.readLine();
311 			while ((line = reader.readLine()) != null) {
312 				HashMap<String, Object> p = new HashMap<String, Object>();
313 				StringTokenizer tokenizer = new StringTokenizer(line, " ", true);
314 				StringBuffer last = new StringBuffer();
315 				int col = 0;
316 				while (tokenizer.hasMoreTokens()) {
317 					String token = tokenizer.nextToken();
318 					switch (col) {
319 					case 0:
320 						if (!" ".equals(token)) {
321 							//
322 							p.put("pid", token);
323 							col++;
324 						}
325 						break;
326 					default:
327 						last.append(token);
328 						break;
329 					}
330 				}
331 
332 				p.put("command", last.toString().trim());
333 				ret.add(p);
334 			}
335 		} catch (IOException e) {
336 
337 		}
338 
339 		return ret;
340 	}
341 
killProcess(String pattern)342 	public static void killProcess(String pattern) {
343 		List<HashMap<String, Object>> processes = SystemUtil.getProcesses();
344 		for (HashMap<String, Object> p : processes) {
345 			String command = (String) p.get("command");
346 			String pid = (String) p.get("pid");
347 			if (command != null && command.matches(pattern)) {
348 				if (isWindows()) {
349 					exec(new String[] { "taskkill", "/F", "/PID", pid }, null, null, null, null);
350 				} else {
351 					exec(new String[] { "kill", "-9", pid }, null, null, null, null);
352 				}
353 			}
354 		}
355 	}
356 
hasProcess(String pattern)357 	public static boolean hasProcess(String pattern) {
358 		return findProcess(pattern) != null;
359 	}
360 
findProcess(String pattern)361 	public static HashMap<String, Object> findProcess(String pattern) {
362 		List<HashMap<String, Object>> processes = SystemUtil.getProcesses();
363 		for (HashMap<String, Object> p : processes) {
364 			String command = (String) p.get("command");
365 			if (command != null && command.matches(pattern)) {
366 				return p;
367 			}
368 		}
369 
370 		return null;
371 	}
372 
findProcesses(String pattern)373 	public static List<HashMap<String, Object>> findProcesses(String pattern) {
374 		List<HashMap<String, Object>> result = new ArrayList<HashMap<String, Object>>();
375 		List<HashMap<String, Object>> processes = SystemUtil.getProcesses();
376 		for (HashMap<String, Object> p : processes) {
377 			String command = (String) p.get("command");
378 			if (command != null && command.matches(pattern)) {
379 				result.add(p);
380 			}
381 		}
382 
383 		return result;
384 	}
385 
386 	/**
387 	 * Get Information of running processes
388 	 *
389 	 */
getProcessPerfData(String processId)390 	public static HashMap<String, Object> getProcessPerfData(String processId) {
391 		try {
392 			StringBuffer output = new StringBuffer();
393 			if (isWindows()) {
394 				File file = new File(SCRIPT_TEMP_DIR, "pps.vbs");
395 				String contents = "Set wmi=GetObject(\"Winmgmts:\")\n\r"
396 						+ "Set pps = wmi.ExecQuery(\"Select * from Win32_PerfFormattedData_PerfProc_Process Where IDProcess='" + processId+"'\")\n\r"
397 						+ "WScript.Echo \"pcpu PrivateBytes WorkingSet HandleCount\" \n\r"
398 						+ "For Each pp in pps \n\r"
399 						+ "WScript.Echo pp.PercentProcessorTime & \" \" & Round(pp.PrivateBytes/1024) & \" \" & Round(pp.WorkingSet/1024) & \" \" & pp.HandleCount \n\r"
400 						+ "Next";
401 //				String contents = "var wmi = GetObject(\"Winmgmts:\");\n"
402 //						+ "var pps = new Enumerator(wmi.ExecQuery(\"Select * from Win32_PerfFormattedData_PerfProc_Process Where IDProcess='" + processId+"'\"));\n"
403 //						+ "WScript.Echo(\"pcpu rss\");\n"
404 //						+ "for ( ; !pps.atEnd(); pps.moveNext()) {\n"
405 //						+ "var pp = pps.item();\n"
406 //						+ "WScript.Echo(pp.PercentProcessorTime + \" \" + (pp.WorkingSet/1024));\n"
407 //						+ "}";
408 				FileUtil.writeStringToFile(file.getAbsolutePath(), contents);
409 				exec(new String[] { "cscript", "//Nologo", file.getAbsolutePath()}, null, null, output, output);
410 			} else {
411 				exec(new String[] {"ps", "-p", processId ,"-o", "pcpu,vsz,rss,tty"}, null, null, output, output);
412 			}
413 			BufferedReader reader = new BufferedReader(new StringReader(output.toString()));
414 			String line = null;
415 			reader.readLine();
416 			if ((line = reader.readLine()) != null) {
417 				HashMap<String, Object> p = new HashMap<String, Object>();
418 				StringTokenizer tokenizer = new StringTokenizer(line, " ", true);
419 				int col = 0;
420 				while (tokenizer.hasMoreTokens()) {
421 					String token = tokenizer.nextToken();
422 					switch (col) {
423 					case 0:
424 						if (!" ".equals(token)) {
425 							//
426 							p.put("pcpu", Double.parseDouble(token));
427 							col++;
428 						}
429 						break;
430 					case 1:
431 						if (!" ".equals(token)) {
432 							//
433 							p.put("vsz", Long.parseLong(token));
434 							col++;
435 						}
436 						break;
437 					case 2:
438 						if (!" ".equals(token)) {
439 							//
440 							p.put("rss", Long.parseLong(token));
441 							col++;
442 						}
443 						break;
444 					case 3:
445 						if (!" ".equals(token)) {
446 							//
447 							try {
448 								p.put("handles", Long.parseLong(token));
449 							} catch (Exception e) {
450 								p.put("handles", 0l);
451 							}
452 
453 							col++;
454 						}
455 						break;
456 					}
457 				}
458 				return p;
459 			}
460 		} catch (IOException e) {
461 
462 		}
463 
464 		return null;
465 	}
466 
467 	/**
468 	 * parse a string to arguments array.
469 	 *
470 	 * @param line
471 	 * @return
472 	 */
parseCommandLine(String line)473 	public static String[] parseCommandLine(String line) {
474 		ArrayList<String> arguments = new ArrayList<String>();
475 		StringTokenizer tokenizer = new StringTokenizer(line, "\"\' ", true);
476 		int state = 0;
477 		StringBuffer current = new StringBuffer();
478 		while (tokenizer.hasMoreTokens()) {
479 			String token = tokenizer.nextToken();
480 			switch (state) {
481 			case 1:
482 				if ("\'".equals(token)) {
483 					state = 3;
484 				} else {
485 					current.append(token);
486 				}
487 				break;
488 			case 2:
489 				if ("\"".equals(token)) {
490 					state = 3;
491 				} else {
492 					current.append(token);
493 				}
494 				break;
495 			default:
496 				if ("\'".equals(token)) {
497 					state = 1;
498 				} else if ("\"".equals(token)) {
499 					state = 2;
500 				} else if (" ".equals(token)) {
501 					if (current.length() > 0) {
502 						arguments.add(current.toString());
503 						current = new StringBuffer();
504 					}
505 				} else {
506 					current.append(token);
507 				}
508 				break;
509 			}
510 		}
511 		if (current.length() > 0)
512 			arguments.add(current.toString());
513 		return arguments.toArray(new String[arguments.size()]);
514 	}
515 
516 	/**
517 	 * Get local host's IP
518 	 * @return
519 	 */
getIPAddress()520 	public static String getIPAddress() {
521 		try {
522 			return InetAddress.getLocalHost().getHostAddress().toString();
523 		} catch (UnknownHostException e) {
524 			return null;
525 		}
526 	}
527 
528 	/**
529 	 * Get local host name
530 	 * @return
531 	 */
getHostName()532 	public static String getHostName() {
533 		try {
534 			return InetAddress.getLocalHost().getHostName();
535 		} catch (UnknownHostException e) {
536 			return null;
537 		}
538 
539 	}
540 
getClassesInPackage(String packageName)541 	public static List<String> getClassesInPackage(String packageName) {
542 		ArrayList<String> classes = new ArrayList<String>();
543 		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
544 		String path = packageName.replace('.', '/');
545 		try {
546 			Enumeration<URL> urls = classLoader.getResources(path);
547 			while (urls.hasMoreElements()) {
548 				URL url = urls.nextElement();
549 				if ("file".equals(url.getProtocol())) {
550 					findClasses(packageName, new File(url.toURI()), classes);
551 				} else if ("jar".equals(url.getProtocol())) {
552 					String urlStr = url.toString();
553 					int i = urlStr.indexOf('!');
554 					if (i > 0)
555 						findClasses(packageName, new URL(urlStr.substring(4, i)), classes);
556 				}
557 			}
558 		} catch (Exception e) {
559 			e.printStackTrace();
560 		}
561 //		TreeSet classes = new TreeSet();
562 //		for (String directory : dirs) {
563 //			classes.addAll(findClasses(directory, packageName));
564 //		}
565 //		ArrayList classList = new ArrayList();
566 //		for (String clazz : classes) {
567 //			classList.add(Class.forName(clazz));
568 //		}
569 //		return classList;
570 		return classes;
571 	}
findClasses(String packageName, File dir, List<String> classes)572 	private static void findClasses(String packageName, File dir, List<String> classes) {
573 		if (!dir.isDirectory())
574 			return;
575 		File[] files = dir.listFiles();
576 		for (File file : files) {
577 			String name = file.getName();
578 			if (file.isDirectory()) {
579 				findClasses(packageName + '.'+ name, file, classes);
580 			}  else if (name.endsWith(".class")) {
581 				String className = packageName + '.' + name.substring(0, name.length() - 6);
582 				classes.add(className);
583 			}
584 		}
585 	}
586 
587 
findClasses(String packageName, URL jar, List<String> classes)588 	private static void findClasses(String packageName, URL jar, List<String> classes) {
589 		try {
590 			ZipInputStream zip = new ZipInputStream(jar.openStream());
591 			ZipEntry entry;
592 			while ((entry = zip.getNextEntry()) != null) {
593 				String name = entry.getName();
594 				if (name.endsWith(".class")) {
595 					name = name.replace('/', '.').substring(0, name.length() - 6);
596 					if (name.startsWith(packageName)) {
597 						classes.add(name);
598 					}
599 				}
600 			}
601 
602 		} catch (Exception e) {
603 
604 		}
605 	}
606 }
607