package javaforce.linux; import java.io.*; import java.util.*; import javaforce.*; import javaforce.utils.*; /** * Cache of .desktop files * * @author pquiring * * Created : Jan 9, 2014 */ public class DesktopCache implements monitordir.Listener { public static class Desktop { public String icon, file, name, exec, all; } private static Vector<Desktop> desktops = new Vector<Desktop>(); //synchronized private static void buildCache(File folder) { File files[] = folder.listFiles(); for(int a=0;a<files.length;a++) { try { if (files[a].isDirectory()) { buildCache(files[a]); continue; } String file = files[a].getAbsolutePath(); if (!file.endsWith(".desktop")) continue; FileInputStream fis = new FileInputStream(files[a]); byte data[] = JF.readAll(fis); String str = new String(data); String lns[] = str.split("\n"); String name = null, icon = null, type = null, exec = null; boolean desktopEntry = false; for(int b=0;b<lns.length;b++) { if (lns[b].startsWith("[Desktop Entry]")) { desktopEntry = true; continue; } if (lns[b].startsWith("[")) desktopEntry = false; if (!desktopEntry) continue; if (lns[b].startsWith("Name=")) {name = lns[b].substring(5); continue;} if (lns[b].startsWith("Icon=")) {icon = lns[b].substring(5); continue;} if (lns[b].startsWith("Type=")) {type = lns[b].substring(5); continue;} if (lns[b].startsWith("Exec=")) {exec = lns[b].substring(5); continue;} } if ((name == null) || (icon == null) || (type == null)) continue; if (!type.equals("Application")) continue; boolean exists = false; for(int b=0;b<desktops.size();b++) { if (desktops.get(b).name.equals(name)) {exists = true; break;} } if (exists) continue; Desktop app = new Desktop(); app.icon = icon; app.name = name; app.file = file; app.exec = exec; app.all = str.toLowerCase(); desktops.add(app); } catch (Exception e) { JFLog.log(e); } } } public synchronized static void buildCache() { File file1 = new File("/usr/share/applications"); if (file1.exists() && file1.isDirectory()) { buildCache(file1); monitorDir(file1); } File file2 = new File(JF.getUserPath() + "/.local/share/applications"); if (file2.exists() && file2.isDirectory()) { buildCache(file2); monitorDir(file2); } } private static ArrayList<String> monitors = new ArrayList<String>(); private static synchronized void monitorDir(File folder) { String fullpath = folder.getAbsolutePath(); for(int a=0;a<monitors.size();a++) { if (monitors.get(a).equals(fullpath)) return; } if (!monitordir.init()) { JFLog.log("DesktopCache:Error:Could not init monitordir"); } int wd = monitordir.add(fullpath); monitordir.setListener(wd, new DesktopCache()); monitors.add(fullpath); } private static String readFile(String file) { try { FileInputStream fis = new FileInputStream(file); //NOTE: fis.available() is ALWAYS zero byte data[] = new byte[1024]; int pos = 0; do { int read = fis.read(data, pos, 1024 - pos); if (read <= 0) break; pos += read; } while (pos < 1024); fis.close(); return new String(data, 0, pos); } catch (Exception e) { return null; } } private static boolean isInterpreter(String cmd) { if (cmd.equals("bash")) return true; if (cmd.equals("wine")) return true; if (cmd.equals("python")) return true; return false; } public static String getDesktopFromPID(int pid) { if (pid == -1) return null; try { String cmdline = readFile("/proc/" + pid + "/cmdline"); if (cmdline == null) return null; String args[] = cmdline.split(new String(new char[] {0})); String stat = readFile("/proc/" + pid + "/stat"); if (stat == null) return null; String stats[] = stat.split(" "); int ppid = JF.atoi(stats[3]); String cmd = args[0]; int idx = cmd.lastIndexOf('/'); if (idx != -1) cmd = cmd.substring(idx+1); if (isInterpreter(cmd)) { cmd = args[1]; idx = cmd.lastIndexOf('/'); if (idx != -1) cmd = cmd.substring(idx+1); } if (cmd.equals("java")) { //try parent process if (ppid > 0) return getDesktopFromPID(ppid); return null; } // JFLog.log("cmd for " + pid + "=" + cmd); //test return DesktopCache.getDesktopFromExec(cmd); } catch (Exception e) { JFLog.log(e); } return null; } public static String getDesktopFromExec(String exec) { for(int a=0;a<desktops.size();a++) { Desktop app = desktops.get(a); String appExec = app.exec; int idx = appExec.lastIndexOf('/'); if (idx != -1) appExec = appExec.substring(idx + 1); if (appExec.equalsIgnoreCase(exec)) return app.file; } return null; } public static String getDesktopFromText(String text) { text = text.toLowerCase(); int idx; idx = text.indexOf(' '); if (idx != -1) text = text.substring(0, idx); idx = text.indexOf('-'); if (idx != -1) text = text.substring(0, idx); idx = text.indexOf('/'); if (idx != -1) text = text.substring(0, idx); idx = text.indexOf('~'); if (idx != -1) text = text.substring(0, idx); for(int a=0;a<desktops.size();a++) { Desktop app = desktops.get(a); if (app.all.indexOf(text) != -1) return app.file; } return null; } public static java.util.List<Desktop> getList() { return desktops; } public void folderChangeEvent(String event, String path) { buildCache(); } }