Search code examples
javalinuxfile-associationjava-5

Cross-platform way to open a file using Java 1.5


I'm using Java 1.5 and I'd like to launch the associated application to open the file. I know that Java 1.6 introduced the Desktop API, but I need a solution for Java 1.5.

So far I found a way to do it in Windows:

Runtime.getRuntime().exec(new String[]{ "rundll32", 
                          "url.dll,FileProtocolHandler", fileName });

Is there a cross-platform way to do it? Or at least a similar solution for Linux?


Solution

  • +1 for this answer

    Additionally I would suggest the following implementation using polymorphism:

    This way you can add new platform easier by reducing coupling among classes.

    The Client code:

     Desktop desktop = Desktop.getDesktop();
    
     desktop.open( aFile );
     desktop.imaginaryAction( aFile );
    

    The Desktop impl:

    package your.pack.name;
    
    import java.io.File;
    
    public class Desktop{
    
        // hide the constructor.
        Desktop(){}
    
        // Created the appropriate instance
        public static Desktop getDesktop(){
    
            String os = System.getProperty("os.name").toLowerCase();
    
            Desktop desktop = new Desktop();
             // This uf/elseif/else code is used only once: here
            if ( os.indexOf("windows") != -1 || os.indexOf("nt") != -1){
    
                desktop = new WindowsDesktop();
    
            } else if ( os.equals("windows 95") || os.equals("windows 98") ){
    
                desktop = new Windows9xDesktop();
    
            } else if ( os.indexOf("mac") != -1 ) {
    
                desktop = new OSXDesktop();
    
            } else if ( os.indexOf("linux") != -1 && isGnome() ) {
    
                desktop = new GnomeDesktop();
    
            } else if ( os.indexOf("linux") != -1 && isKde() ) {
    
                desktop = new KdeDesktop();
    
            } else {
                throw new UnsupportedOperationException(String.format("The platform %s is not supported ",os) );
            }
            return desktop;
        }
    
        // default implementation :( 
        public void open( File file ){
            throw new UnsupportedOperationException();
        }
    
        // default implementation :( 
        public void imaginaryAction( File file  ){
            throw new UnsupportedOperationException();
        }
    }
    
    // One subclass per platform below:
    // Each one knows how to handle its own platform   
    
    
    class GnomeDesktop extends Desktop{
    
        public void open( File file ){
            // Runtime.getRuntime().exec: execute gnome-open <file>
        }
    
        public void imaginaryAction( File file ){
            // Runtime.getRuntime().exec:gnome-something-else <file>
        }
    
    }
    class KdeDesktop extends Desktop{
    
        public void open( File file ){
            // Runtime.getRuntime().exec: kfmclient exec <file>
        }
    
        public void imaginaryAction( File file ){
            // Runtime.getRuntime().exec: kfm-imaginary.sh  <file>
        }
    }
    class OSXDesktop extends Desktop{
    
        public void open( File file ){
            // Runtime.getRuntime().exec: open <file>
        }
    
        public void imaginaryAction( File file ){
            // Runtime.getRuntime().exec: wow!! <file>
        }
    }
    class WindowsDesktop extends Desktop{
    
        public void open( File file ){
            // Runtime.getRuntime().exec: cmd /c start <file>
        }
    
        public void imaginaryAction( File file ){
            // Runtime.getRuntime().exec: ipconfig /relese /c/d/e
        }
    }
    class Windows9xDesktop extends Desktop{
    
        public void open( File file ){
            //Runtime.getRuntime().exec: command.com /C start <file>
        }
    
        public void imaginaryAction( File file){
           //Runtime.getRuntime().exec: command.com /C otherCommandHere <file>
        }
    }
    

    This is only an example, in real life is not worth to create a new class only to parametrize a value ( the command string %s ) But let's do imagine that each method performs another steps in platform specific way.

    Doing this kind of approach, may remove unneeded if/elseif/else constructs that with time may introduce bugs ( if there are 6 of these in the code and a change is neede, you may forget to update one of them, or by copy/pasting you may forget to change the command to execute)