001: package snow.utils;
002:
003: import java.net.URI;
004: import java.awt.Desktop;
005: import javax.swing.JOptionPane;
006: import javax.swing.JFileChooser;
007: import java.util.prefs.Preferences;
008: import java.io.*;
009: import java.util.*;
010:
011: /** System utilities, normally working on Windows and on Linux.
012: * Windows XP: ok. 2000 needs sysinternals shutdown utility...
013: * Suse Linux:ok, Unbuntu:ok
014: */
015: public final class SysUtils {
016: private SysUtils() {
017: }
018:
019: /** On windows, single files are "executed" by the system, with the associated file.
020: */
021: public static void openFileExplorer(File dir) {
022:
023: if (Desktop.isDesktopSupported()) {
024: try {
025: Desktop.getDesktop().open(dir);
026: return;
027: } catch (Exception e) {
028: e.printStackTrace();
029: // try below
030: }
031: }
032:
033: if (System.getProperty("os.name", "Windows").toLowerCase()
034: .indexOf("windows") >= 0) {
035: try {
036: String wname = dir.getAbsolutePath().replaceAll("/",
037: "\\\\").trim();
038: if (wname.indexOf(' ') > 0) {
039: // the /e does not work here !!! :-((
040: ProcessUtils.executeProcessAndGobble(Arrays.asList(
041: "explorer.exe", "\"" + wname + "\""),
042: "open explorer");
043: } else {
044: // /e to open the explorer with the left tree...
045: ProcessUtils.executeProcessAndGobble(Arrays.asList(
046: "explorer.exe", "/e," + wname),
047: "open explorer");
048: }
049: } catch (Exception e) {
050: e.printStackTrace();
051: }
052: } else if (System.getProperty("os.name", "linux").toLowerCase()
053: .indexOf("linux") >= 0) {
054: try {
055: // spaces ??
056: ProcessUtils.executeProcessAndGobble(Arrays.asList(
057: System.getProperty("os.filebrowser",
058: "konqueror"), "" + dir),
059: "open explorer");
060: } catch (Exception e) {
061: e.printStackTrace();
062: }
063: }
064: }
065:
066: public static void openBrowser(final String url) throws Exception {
067: if (Desktop.isDesktopSupported()) {
068: // Fedora8: fails to open firefox for local html... (TODO).
069:
070: try {
071: Desktop.getDesktop().browse(
072: new URI(url.replace('\\', '/')));
073: return;
074: } catch (Exception e) {
075: System.out
076: .println("Can't Desktop.browse '" + url + "'");
077: e.printStackTrace();
078: // try below
079: }
080: }
081:
082: if (is_Windows_OS()) {
083: Process p = Runtime.getRuntime().exec(
084: "rundll32 url.dll,FileProtocolHandler " + url);
085: ProcessUtils.drainProcess(p, false);
086: } else if (is_MAC_OS()) {
087: Process p = Runtime.getRuntime().exec(
088: "open -b com.apple.Safari " + url);
089: ProcessUtils.drainProcess(p, false);
090: } else // linux
091: {
092: // [July2007]: Not working well
093: try {
094: Process p = Runtime.getRuntime().exec(
095: "mozilla -remote openURL (" + url + ")");
096: ProcessUtils.drainProcess(p, false);
097: if (p.waitFor() != 0) {
098: // or konqueror or iceweasel
099: p = Runtime.getRuntime().exec("mozilla " + url);
100: ProcessUtils.drainProcess(p, false);
101: if (p.waitFor() != 0) {
102: openDocumentInSystem(url, true);
103: }
104: }
105: } catch (Exception ex) {
106: openDocumentInSystem(url, true);
107: //throw ex;
108: }
109: }
110: }
111:
112: /** Suitable for pdf, txt, ...
113: */
114: public static void openDocumentInSystem(
115: final String absoluteLinkPath, boolean isHTTP)
116: throws Exception {
117: try {
118: String[] cmd = null;
119: if (SysUtils.is_Windows_OS()) {
120: cmd = isHTTP ? new String[] { "cmd", "/c", "start",
121: absoluteLinkPath } : new String[] { "cmd",
122: "/c", absoluteLinkPath };
123: } else if (is_MAC_OS()) {
124: cmd = new String[] { "open -b com.apple.Safari "
125: + absoluteLinkPath };
126: } else {
127: if (System.getProperty("sun.desktop", "").contains(
128: "gnome")) {
129: cmd = new String[] { "/usr/bin/gnome-open",
130: absoluteLinkPath };
131: } else {
132: cmd = new String[] { "kfmclient", "exec",
133: absoluteLinkPath };
134: }
135: }
136: ProcessUtils.executeProcessAndGobbleToConsole(
137: "OpenDocInSystem", null, cmd);
138: } catch (IOException ioex) {
139: //ioex.printStackTrace();
140: throw ioex;
141: }
142: }
143:
144: public static void lockWorkStation() {
145: try {
146: Process p = ProcessUtils.executeProcessAndGobbleToConsole(
147: "lock workstation", null, "rundll32", "user32.dll",
148: "LockWorkStation");
149: } catch (Exception e) {
150: e.printStackTrace();
151: }
152: }
153:
154: /** NOTE: can be undone with the command "shutdown -a".
155: * 2000: must install a tool: http://www.microsoft.com/technet/sysinternals/utilities/psshutdown.mspx
156: * XP: must have the correct policy set.
157: *
158: * if the windows command fails (too less privileges), calls sysinternals.
159: *XP: if failing, says (STUPID!)
160: SysUtils> The operation completed successfully.
161: SysUtils> A required privilege is not held by the client.
162:
163: =>I Prefer using always sysinternals...
164: */
165: public static void shutdown(final int delaySec,
166: final boolean restart, String comment_,
167: final boolean forceUsingSysInternals) throws Exception {
168: if (is_Windows_OS()) // only XP?
169: {
170: System.out.println("Shutdown windows");
171: if (comment_ != null) {
172: comment_ = comment_.replace('"', '\'');
173: }
174:
175: final String comment = comment_;
176:
177: if (forceUsingSysInternals
178: || System.getProperty("os.name").contains("2000")) {
179: String st = Preferences.userRoot().get(
180: "shutdown_tool_loc", "");
181: System.out.println("pstool: " + st);
182: if (st != null && st.length() > 0) {
183: File stf = new File(st);
184: if (stf.exists()) {
185: // pops up a nice dialog also allowing to cancel. (30 sec)
186: Process p = ProcessUtils
187: .executeProcessAndGobbleToConsole(
188: "shutdowncmd", stf
189: .getParentFile(),
190: "cmd", "start /C", stf
191: .getName(), "-c", "-t",
192: "" + delaySec, "-m", comment);
193: System.out.println("Shutting down with pstool");
194: }
195: }
196: } else {
197: // only xp+
198: // can be annulated with the command shutdown -a
199: final Process p = ProcessUtils
200: .executeProcessAndGobbleToConsole(
201: "shutdowncmd", null, "cmd",
202: "start /C shutdown "
203: + (restart ? "-r" : "-s")
204: + " -c "
205: + (comment != null ? "\""
206: + comment + "\"" : "")
207: + " -t " + delaySec); // -f
208:
209: // if process fails => use sys internals...
210: Thread t = new Thread() {
211: @Override
212: public void run() {
213: System.out.println("Waiting shutdown response");
214: try {
215: Thread.sleep(1000);
216: if (p.waitFor() != 0) // WAITS... to detect errors... FAILING (SEE ABOVE)
217: {
218: // forceUsingSysInternals
219: if (checkShutdown(true)) {
220: System.out
221: .println("System shutdown failed, try sysinternals");
222: shutdown(delaySec, restart,
223: comment, true); // CALL ITSELF: ok, no infinite loop.
224: }
225:
226: }
227: } catch (Exception e) {
228: e.printStackTrace();
229: }
230: }
231: };
232: t.start();
233: }
234: } else {
235: // TODO...
236: // this asks for password on system.in
237: String reply = ProcessUtils.readWholeProcessStack(Arrays
238: .asList("/bin/sh", "-c", "sudo shutdown "
239: + (restart ? "-r " : "") + " now"), 15000L);
240: if (reply == null || reply.trim().length() > 0) {
241: System.out.println("Cannot shutdown:\n" + reply);
242: }
243: }
244: }
245:
246: /** Asks for windows 2000: psshutdown.
247: */
248: public static boolean checkShutdown(boolean forceUsingPSTool) {
249: if (forceUsingPSTool
250: || System.getProperty("os.name").contains("2000")) {
251: String st = Preferences.userRoot().get("shutdown_tool_loc",
252: "");
253: if (st != null && st.length() > 0) {
254: File stf = new File(st);
255: if (stf.exists())
256: return true;
257: }
258:
259: int rep = JOptionPane
260: .showConfirmDialog(
261: null,
262: "The external psshutdown tool is required."
263: + "\n\nYou can download manually the tool psshutdown of SysInternals at"
264: + "\n http://www.microsoft.com/technet/sysinternals/utilities/psshutdown.mspx"
265: + "\n\nAnd then specify its location hereafter. Continue ?",
266: "PsShutdown tool required",
267: JOptionPane.YES_NO_CANCEL_OPTION);
268:
269: if (rep != JOptionPane.OK_OPTION) {
270: return false;
271: }
272:
273: JFileChooser fs = new JFileChooser();
274: fs
275: .setDialogTitle("Please specify the location of psshutdown.exe");
276: rep = fs.showOpenDialog(null);
277: if (rep != JFileChooser.APPROVE_OPTION) {
278: return false;
279: }
280:
281: File repf = fs.getSelectedFile();
282: Preferences.userRoot().put("shutdown_tool_loc",
283: "" + repf.getAbsolutePath());
284:
285: JOptionPane
286: .showMessageDialog(
287: null,
288: "The first time you call psshutdown, a licence message must be manually agreed."
289: + "\nSo be present at the first shutdown, don't go to sleep before!",
290: "Caution", JOptionPane.INFORMATION_MESSAGE);
291:
292: }
293:
294: // assume ok.
295: return true;
296: }
297:
298: /** Asks for windows 2000: pskill
299: */
300: public static boolean checkKill() {
301: if (System.getProperty("os.name").contains("2000")) {
302: String st = Preferences.userRoot().get("kill_tool_loc", "");
303: if (st != null && st.length() > 0) {
304: File stf = new File(st);
305: if (stf.exists())
306: return true;
307: }
308:
309: int rep = JOptionPane
310: .showConfirmDialog(
311: null,
312: "Windows 2000 external pskill tool is required."
313: + "\n\nYou can download manually the tool psshutdown of SysInternals at"
314: + "\n http://www.microsoft.com/technet/sysinternals/utilities/psshutdown.mspx"
315: + "\n\nAnd then specify its location hereafter. Continue ?",
316: "PsKill tool required",
317: JOptionPane.YES_NO_CANCEL_OPTION);
318:
319: if (rep != JOptionPane.OK_OPTION) {
320: return false;
321: }
322:
323: JFileChooser fs = new JFileChooser();
324: fs
325: .setDialogTitle("Please specify the location of pskill.exe");
326: rep = fs.showOpenDialog(null);
327: if (rep != JFileChooser.APPROVE_OPTION) {
328: return false;
329: }
330:
331: File repf = fs.getSelectedFile();
332: Preferences.userRoot().put("kill_tool_loc",
333: "" + repf.getAbsolutePath());
334:
335: JOptionPane
336: .showMessageDialog(
337: null,
338: "The first time you call pskill, a licence message must be manually agreed.",
339: "Caution", JOptionPane.INFORMATION_MESSAGE);
340:
341: }
342:
343: // assume ok.
344: return true;
345: }
346:
347: /**
348: @param windowsGroup is normally "Users"
349: */
350: public static boolean setReadWriteAttribs(final File f,
351: final String windowsGroup) throws Exception {
352: if (is_Windows_OS()) {
353: //
354: System.out.println("setting read-write-access for " + f);
355: String reply = null;
356: if (f.isDirectory()) {
357: reply = ProcessUtils.readWholeProcessStack(Arrays
358: .asList("cmd", "/c", "CACLS", "" + f.getName(),
359: "/t", "/e", "/g", // recursive edit grant
360: windowsGroup + ":f" // Full access !
361: ), f.getParentFile(), Arrays.asList("y\r\n"),
362: 15000L, true // confirmation required: type "yes" or "y" !!
363: );
364: System.out.println("ok ? " + reply);
365: } else {
366: reply = ProcessUtils.readWholeProcessStack(Arrays
367: .asList("cmd", "/c", "CACLS", "" + f.getName(),
368: "/e", "/g", // edit grant
369: windowsGroup + ":f"), // Full access !
370:
371: f.getParentFile(),
372:
373: Arrays.asList("y\r\n"), 15000L, true // confirmation required: type "yes" or "y" !!
374:
375: );
376: System.out.println("set. " + reply);
377: }
378:
379: /*reply = reply.trim();
380: if(reply.length()>0)
381: {
382: System.out.println("Can't set the readwrite for all for "+reply);
383: return false;
384: }*/
385: } else {
386: try {
387: if (f.isDirectory()) {
388: String reply = ProcessUtils.readWholeProcessStack(
389: Arrays.asList("/bin/sh", "-c",
390: "chmod -R 777 " + f.getName()), f
391: .getParentFile(), 15000L);
392: if (reply == null || reply.trim().length() > 0) {
393: System.out
394: .println("Cannot set read write file access for folder "
395: + f + ":\n" + reply);
396: return false;
397: }
398: return true;
399: } else {
400: String reply = ProcessUtils.readWholeProcessStack(
401: Arrays.asList("/bin/sh", "-c", "chmod 777 "
402: + f.getName()), f.getParentFile(),
403: 15000L);
404: if (reply == null || reply.trim().length() > 0) {
405: System.out
406: .println("Cannot set read write file access for file "
407: + f + ":\n" + reply);
408: return false;
409: }
410: return true;
411: }
412: } catch (Exception ex) {
413: ex.printStackTrace();
414: return false;
415: }
416: }
417: return true;
418: }
419:
420: public static boolean is_Windows_OS() {
421: if (System.getProperty("os.name", "windows").toLowerCase()
422: .indexOf("win") >= 0)
423: return true;
424:
425: return false;
426: }
427:
428: public static boolean is_MAC_OS() {
429: if (System.getProperty("os.name", "windows").toLowerCase()
430: .indexOf("mac") >= 0)
431: return true;
432:
433: return false;
434: }
435:
436: /** Sometimes fail !!!, the process say "SUCCESS: has been terminated",
437: * but the process stil lives ! and jps says "( process information unavailable)"
438: */
439: public static void killProcess(final String id) throws Exception {
440: if (is_Windows_OS()) // XP?
441: {
442: System.out.println("Killing process " + id);
443:
444: if (System.getProperty("os.name").contains("2000")) {
445: // use ext sys int pskill
446: if (checkKill()) {
447: String st = Preferences.userRoot().get(
448: "kill_tool_loc", "");
449: ProcessUtils.executeProcessAndGobbleToConsole(
450: "kill proc", null, "" + st, "-t", id);
451: return;
452: }
453: }
454:
455: // [Nov2007]: added /F to force... (XP)
456: ProcessUtils.executeProcessAndGobbleToConsole("kill proc",
457: null, "cmd", "/C", "taskkill", "/F", "/pid", id);
458: } else {
459: ProcessUtils.executeProcessAndGobbleToConsole("kill proc",
460: null, "kill", id);
461: }
462: }
463:
464: /* sysinternals
465: Usage: pskill [-t] [\\computer [-u username [-p password]]] <process ID | name>
466: -t Kill the process and its descendants.
467: -u Specifies optional user name for login to
468: remote computer.
469: -p Specifies optional password for user name. If you omit this
470: you will be prompted to enter a hidden password.
471: */
472:
473: public static void printPDF(final String pdfPath) throws Exception {
474: if (is_Windows_OS()) {
475: // found on lowagie homepage.
476: String osName = System.getProperty("os.name");
477: //FOR WINDOWS 95 AND 98 USE COMMAND.COM
478: if (osName.equals("Windows 95")
479: || osName.equals("Windows 98")) {
480: Runtime.getRuntime()
481: .exec(
482: "command.com /C start acrord32 /p /h"
483: + pdfPath);
484: }
485: //FOR WINDOWS NT/XP/2000 USE CMD.EXE
486: else {
487: Runtime.getRuntime().exec(
488: "cmd.exe start /C acrord32 /p /h" + pdfPath);
489: }
490: } else {
491: // ??
492: Desktop.getDesktop().print(new File(pdfPath));
493: //Runtime.getRuntime().exec(pdfPath);
494: }
495: }
496:
497: // allow possibility to "undo" the redirection.
498: private static OutputStream originalSystemOut = null;
499:
500: /** Redirects System.out and System.err to the given file.
501: */
502: public static final void redirectSystemOutput(final String logPath,
503: final boolean debug) {
504: final String log = logPath;
505: if (originalSystemOut == null) {
506: originalSystemOut = System.out;
507: }
508:
509: System.out.println("redirecting console to " + log);
510: try {
511: FileOutputStream fos = new FileOutputStream(log, true) // append mode
512: {
513: @Override
514: public synchronized void write(final int b)
515: throws IOException {
516: super .write(b);
517: if (debug)
518: originalSystemOut.write(b);
519: }
520:
521: @Override
522: public synchronized void write(final byte[] b,
523: final int off, final int len)
524: throws IOException {
525: super .write(b, off, len);
526: if (debug)
527: originalSystemOut.write(b, off, len);
528: }
529:
530: @Override
531: public synchronized void write(final byte[] b)
532: throws IOException {
533: super .write(b);
534: if (debug)
535: originalSystemOut.write(b);
536: }
537: };
538:
539: PrintStream redirectPrintStream = new PrintStream(fos, true); // autoflush
540: System.setErr(redirectPrintStream);
541: System.setOut(redirectPrintStream);
542: } catch (Exception ex) {
543: ex.printStackTrace();
544: System.out
545: .println("Error redirecting System out to logfile."
546: + ex.getMessage());
547: }
548: }
549:
550: /*test*/
551: public static void main(String[] arguments) throws Exception {
552: lockWorkStation();
553:
554: if (true)
555: return;
556:
557: //SysUtils.openBrowser("http://localhost:7000");
558: //shutdown(57, false, "Hello");
559: checkShutdown(true);
560: shutdown(30, false, "Hello", true);
561: //Desktop.getDesktop().browse(new URI("file://c:/temp")); // ok
562: //Desktop.getDesktop().browse(new URI("http://java.sun.com")); // ok
563:
564: Desktop
565: .getDesktop()
566: .mail(
567: new URI(
568: "mailto:stephan.heiss@gmail.com?subject=from%20a%20tIDE%20java%20IDE%20user&body=...Please%20enter%20your%20remark%20or%20bugfix%20or%20comment%20here...%0D%0A"));
569:
570: //mailto:a@b")); // look at (RFC 2368)
571: }
572:
573: }
|