Listing 4

public class AssociationService {
   private String m_ApplicationID;
   private String m_ApplicationName;
   private String m_Description;
   private Class m_MainClass;
   private Class m_ResourceClass;
   private String m_ApplicationDir;
   private Iterable m_Associations;
   private boolean m_Install;
   private boolean m_SystemInstall;
   private String m_RootPassword = null;
   private String m_SudoStr = null;
   private String m_XDGModeStr = null;
   private Shell m_Shell = new Shell();
   private String quotedQuote(String str) {
      return "\\\"" + str + "\\\"";
   }

   private String quote(String str) {
      return "\"" + str + "\"";
   }

   private String getCodeBase() {
      String cp = System.getProperty("java.class.path");
      int i = cp.indexOf(File.pathSeparator);
      return new File(cp.substring(0, i < 0 ? cp.length() : i)).getAbsolutePath();

   }

   private String getAppDir(String codeBase) {
      int i = codeBase.lastIndexOf(File.separator);
      return codeBase.substring(0, i < 0 ? codeBase.length() : i);
   }

   private String getGnomeDir() {
      String gnomeDir = System.getenv("GNOMEDIR");
      if (m_SystemInstall) {
         if (gnomeDir != null)
            gnomeDir += "/share";
         else
            gnomeDir = "/usr/share/gnome";
      } else
         gnomeDir = System.getProperty("user.home") + "/.gnome";
      return gnomeDir;
   }

   private boolean sudo(String cmd, boolean fail) throws Exception {
      m_Shell.sudoExecute(cmd, null, m_RootPassword);
      if (fail && m_Shell.getExitCode() != 0)
         throw new Exception("sudo failure, exit code " + m_Shell.getExitCode() + ", command line: " + m_Shell.getCommand());
      return m_Shell.getExitCode() == 0;
   }

   /**
    * Copies a resorce to a file.
    * A non essential but nonetheless usefull, hence public, helper function that copies a named resource from the given class to
    * the given file.
    * @param clss
    * @param resource
    * @param toFile
    * @throws IOException
    */
   static public void copyResourceToFile(Class clss, String resource, File toFile) throws IOException {
      InputStream input = clss.getResourceAsStream(resource);
      if (input == null)
         throw new IllegalArgumentException("Could not get resource " + resource + " from class " + clss.getName());
      else {
         OutputStream output = null;
         IOException ioe = null;
         try {
            output = new FileOutputStream(toFile);
            byte b[] = new byte[10 * 1024];
            int n;
            while ((n = input.read(b)) > 0)
               output.write(b, 0, n);
         } catch (IOException e) {
            ioe = e;
         } finally {
            if (input != null)
               try {
                  input.close();
               } catch (IOException e) {
                  ioe = e;
               }
            if (output != null)
               try {
                  output.close();
               } catch (IOException e) {
                  ioe = e;
               }
            if (ioe != null)
               throw ioe;
         }
      }
   }

   void installDotXML() throws Exception {
      String home = System.getProperty("user.home");
      File dotXMLFile = new File(m_ApplicationDir + File.separator + m_ApplicationID + ".xml");
      PrintStream out = new PrintStream(new FileOutputStream(dotXMLFile));

      out.println("");
      out.println(" ");
      for (Association type : m_Associations) {
         if (type.getMimeType() == null)
            continue;
         out.println("  ");
         out.println("    " + type.getDescription() + "");
         String frgmnt = type.getMagicPattern();
         if (frgmnt != null) {
            out.println(frgmnt);
         }
         out.println("    ");
         out.println("  ");
      }

      out.println("");
      out.close();

      if (m_Install)
         XDGUtils.execute(m_Shell, m_SudoStr, "xdg-mime " + "install " + "--mode " + m_XDGModeStr + "--novendor " + dotXMLFile.getAbsolutePath(), m_RootPassword);
      else
         XDGUtils.execute(m_Shell, m_SudoStr, "xdg-mime " + "uninstall " + "--mode " + m_XDGModeStr + dotXMLFile.getAbsolutePath(), m_RootPassword);
   }

   private String getLinuxLaunchCmd() {
      String command;
      String codeBase = getCodeBase();
      if (codeBase.endsWith(".jar"))
         command = "java -jar " + quote(codeBase);
      else
         command = "java -cp " + quote(System.getProperty("java.class.path")) + " " + m_MainClass.getCanonicalName();
      return command + " %F";
   }
   
   private String getMimeTypesString() {
      String mimeTypes = "";
      for (Association type : m_Associations) {
         if (type.getMimeType() == null)
            continue;
         if (mimeTypes.length()>0)
            mimeTypes = mimeTypes+";"+type.getMimeType();
         else 
            mimeTypes = type.getMimeType();
      }
      return mimeTypes;
   }

   private String installDotDesktop() throws Exception {
      String command = getLinuxLaunchCmd();


      String iconName = m_ApplicationID + "-app" + ".png";
      File iconFile = new File(m_ApplicationDir + "/" + iconName);
      copyResourceToFile(m_ResourceClass, iconName, iconFile);

      File dotDesktopFile = new File(m_ApplicationDir + File.separator + m_ApplicationID + ".desktop");
      PrintStream out = new PrintStream(new FileOutputStream(dotDesktopFile));
      out.println("[Desktop Entry]");
      out.println(" Version=1.0");
      out.println(" Type=Application");
      out.println(" Name=" + m_ApplicationName);
      out.println(" Comment=" + m_Description);
      out.println(" Exec=" + command);
      out.println(" Icon=" + iconFile.getAbsolutePath());
      out.println(" MimeType=" + getMimeTypesString());
      out.close();

      if (m_Install) {
         XDGUtils.execute(m_Shell, m_SudoStr, "xdg-desktop-menu " + "install " + "--novendor " + dotDesktopFile.getAbsolutePath(), m_RootPassword);
         XDGUtils.execute(m_Shell, m_SudoStr, "xdg-desktop-icon " + "install " + "--novendor " + dotDesktopFile.getAbsolutePath(), m_RootPassword);
      }
      else {
         XDGUtils.execute(m_Shell, m_SudoStr, "xdg-desktop-menu " + "uninstall " + dotDesktopFile.getAbsolutePath(), m_RootPassword);
         XDGUtils.execute(m_Shell, m_SudoStr, "xdg-desktop-icon " + "uninstall " + dotDesktopFile.getAbsolutePath(), m_RootPassword);
      }
      return command;
   }

   private void installMimeIcons() throws Exception {
      for (Association type : m_Associations) {
         if (type.getMimeType() != null) {

            String iconSourceName = m_ApplicationID + "-doc-" + type.getExtension().substring(1) + ".png";
            File mimeIconFile = new File(m_ApplicationDir + File.separator + iconSourceName);
            copyResourceToFile(m_ResourceClass, iconSourceName, mimeIconFile);

            String iconName = type.getMimeType().replace("/", "-");
            ImageIcon icon = new ImageIcon(m_ResourceClass.getResource(iconSourceName));
            String iconSize = Integer.toString(icon.getIconWidth()) + " ";
            if (m_Install)
               XDGUtils.execute(m_Shell, m_SudoStr, "xdg-icon-resource " + "install " + "--novendor --context mimetypes --size " + iconSize + mimeIconFile.getAbsolutePath() + " " + iconName, m_RootPassword);
            else // following does not work unfortunately
               XDGUtils.execute(m_Shell, m_SudoStr, "xdg-icon-resource " + "uninstall " + "--context mimetypes --size " + iconSize + mimeIconFile.getAbsolutePath() + " " + iconName, m_RootPassword);
         }
      }
   }

   private void installDotMimeFile(String gnomeDir) throws Exception {
      File temp = getTempFile();
      PrintStream out = new PrintStream(new FileOutputStream(temp));
      for (Association type : m_Associations) {
         out.println(type.getMimeType());
         out.print("\t" + "ext:");
         if (type.getExtension() != null)
            out.print(" " + type.getExtension().substring(1));
      }
      out.println();
      out.close();
      File file = new File(gnomeDir + "/mime-info/" + m_ApplicationID + ".mime");
      installTempFile(temp, file);
   }

   private File getTempFile() {
      return new File(m_ApplicationDir + "/temporary-installation-file");
   }

   private void installTempFile(File tempFile, File installTo) throws Exception {
      sudo("cp " + tempFile.getAbsolutePath() + " " + installTo.getAbsolutePath(), true);
      sudo("rm " + tempFile.getAbsolutePath(), true);
   }

   private File installGnomeIcon(String gnomeDir) throws Exception {
      String iconName = m_ApplicationID + "-app" + ".png";
      File temp = getTempFile();
      File iconFile = new File(gnomeDir + "/pixmaps/" + iconName);
      copyResourceToFile(m_ResourceClass, iconName, temp);
      installTempFile(temp, iconFile);
      return iconFile;
   }

   private void installDotKeysFile(String gnomeDir) throws Exception {
      File iconFile = installGnomeIcon(gnomeDir);

      File temp = getTempFile();
      PrintStream out = new PrintStream(new FileOutputStream(temp));
      for (Association type : m_Associations) {
         if (type.getMimeType() != null) {
            out.println(type.getMimeType());
            out.println("\t" + "description=" + m_Description);
            out.println("\t" + "icon_filename=" + iconFile.getAbsolutePath());
            out.println("\t" + "default_action_type=application");
            out.println("\t" + "default_application_id=" + m_ApplicationID);
            out.println("\t" + "short_list_application_user_additions=" + m_ApplicationID);
            out.println();
         }
      }
      out.close();
      File file = new File(gnomeDir + "/mime-info/" + m_ApplicationID + ".keys");
      installTempFile(temp, file);
   }

   private void installDotApplicationsFile(String gnomeDir) throws Exception {
      String command = getLinuxLaunchCmd();

      File tempFile = getTempFile();
      PrintStream out = new PrintStream(new FileOutputStream(tempFile));

      out.println(m_ApplicationID);
      out.println("\t" + "command=" + command);
      out.println("\t" + "name=" + m_ApplicationName);
      out.println("\t" + "can_open_multiple_files=false");
      out.println("\t" + "mime_types=" + getMimeTypesString());
      out.println();
      out.close();
      File file = new File(gnomeDir + "/application-info/" + m_ApplicationID + ".applications");
      installTempFile(tempFile, file);
   }

   private boolean checkGnome(String gnomeDir) {
      File f;
      f = new File(gnomeDir + "/application-registry");
      if (!f.exists()) {
         System.out.println("missing: " + f.getAbsolutePath());
         return false;
      }
      f = new File(gnomeDir + "/application-info");
      if (!f.exists()) {
         System.out.println("missing: " + f.getAbsolutePath());
         return false;
      }
      f = new File(gnomeDir + "/mime-info");
      if (!f.exists()) {
         System.out.println("missing: " + f.getAbsolutePath());
         return false;
      }
      f = new File(gnomeDir + "/pixmaps");
      if (!f.exists()) {
         System.out.println("missing: " + f.getAbsolutePath());
         return false;
      }
      return true;
   }

   void linuxInstall() throws Exception {
      try {
         System.out.println("linux install...");
         m_XDGModeStr = m_SystemInstall ? "system " : "user ";
         m_SudoStr = m_RootPassword != null ? "sudo -S " : "";

         installDotDesktop();
         installDotXML();
         installMimeIcons();

         String gnomeDir = getGnomeDir();

         if (checkGnome(gnomeDir)) {
            installDotMimeFile(gnomeDir);
            installDotKeysFile(gnomeDir);
            installDotApplicationsFile(gnomeDir);
         } else
            System.out.println("gnome (old style) installation not performed");
      } finally {
         // kill user time stamp, no matter what happens
         if (m_RootPassword != null)
            sudo("-K", true);
      }
   }

   private void windowsInstall() throws Exception {

      String codeBase = getCodeBase();
      String appDir = m_ApplicationDir;
      String appRegKey = m_ApplicationID;

      for (Association type : m_Associations) {
         String fileRegKey = appRegKey + "-doc-" + type.getExtension().substring(1);
         String iconName = fileRegKey + ".ico";
         String iconPath = appDir + File.separator + iconName;

         if (m_Install) {
            copyResourceToFile(m_ResourceClass, iconName, new File(iconPath));

            m_Shell.execute("REG ADD HKCR\\" + type.getExtension() + " /f /v \"\" /t REG_SZ /d " + fileRegKey, null);
            m_Shell.execute("REG ADD HKCR\\" + fileRegKey + " /f /v \"\" /t REG_SZ /d " + quote(type.getDescription()), null);
            m_Shell.execute("REG ADD HKCR\\" + fileRegKey + "\\DefaultIcon /f /v \"\" /t REG_SZ /d " + quote(iconPath), null);
            String cmd = "";
            if (codeBase.endsWith(".exe"))
               cmd = quotedQuote(codeBase);
            else if (codeBase.endsWith(".jar"))
               cmd = "java -jar " + quotedQuote(codeBase);
            else
               cmd = "java -cp " + quotedQuote(System.getProperty("java.class.path")) + " " + m_MainClass.getCanonicalName();
            m_Shell.execute("REG ADD HKCR\\" + fileRegKey + "\\shell\\open\\command /f /v \"\" /t REG_SZ /d \"" + cmd + " " + quotedQuote("%1"), null);
         }
         else {
            m_Shell.execute("REG DELETE HKCR\\" + fileRegKey , null);
            m_Shell.execute("REG DELETE HKCR\\" + type.getExtension(), null);
         }
      }

   }

   private void assertNotNull(String argName, Object arg) {
      if (arg == null)
         throw new IllegalArgumentException("Argument '" + argName + "' must not be null.");
   }
   /**
    * Registers/unregister the application and file associations with the platforms Desktop.
    * Registers/unregisters the associations with the platforms Desktop Manager (Gnome/KDE/Finder/Explorer) so that
    * both the application and the documents have the correct appearance (icon) and can be launched/opened
    * by double clicking at the icon on the Desktop.
    * the application lauched b
    * @param install weather to install or uninstall
    * @param systemInstall install into system or for the user (Linux only)
    * @param password the root (admin) password for 'sudo'ing the regisration (Linux only)
    * @param mainClass the mainClass of the application
    * @param resourceClass the class that contains the resources (icons)
    * @param applicationID the internal name for the application (used as key in regisration)
    * @param applicationName the user name for the application
    * @param description the user description of the application
    * @param applicationDir the directory used to store registration related files, needs to be writable
    * @param associations list of associations to register
    * @throws Exception if something goes wrong
    */

   public void register(//
         boolean install,//
         boolean systemInstall,//
         String password,//
         Class mainClass,//
         Class resourceClass,//
         String applicationID,//
         String applicationName,//
         String description, //
         String applicationDir,//
         Iterable associations//
   ) throws Exception {
      assertNotNull("mainClass", mainClass);
      assertNotNull("resourceClass", resourceClass);
      assertNotNull("applicationID", applicationID);
      assertNotNull("applicationName", applicationName);
      assertNotNull("description", description);
      assertNotNull("associations", associations);
      assertNotNull("applicationDir", applicationDir);
      if (!(new File(applicationDir)).exists())
         throw new IllegalArgumentException("Argument applicationDir='" + applicationDir + "' which doens not exist.");
      if (associations.iterator().hasNext() == false)
         throw new IllegalArgumentException("Argument 'associations' cannot be empty.");

      m_Install = install;
      m_SystemInstall = systemInstall;
      m_RootPassword = password;
      m_MainClass = mainClass;
      m_ResourceClass = resourceClass;
      m_ApplicationID = applicationID;
      m_ApplicationName = applicationName;
      m_Description = description;
      m_Associations = associations;
      m_ApplicationDir = applicationDir;

      String osname = System.getProperty("os.name").toLowerCase();
      if (osname.indexOf("window") >= 0)
         windowsInstall();
      if (osname.indexOf("linux") >= 0)
         linuxInstall();
   }
}