JOGL installer for applet

Hi !

I’m working on a simle JOGL installer for applets, based on extension loading. Installer should work with an applet and as standalone Java app. But…
I have encoutered some problems:

[]URL is “” when using getClass().getResource() in app, which worked fine in java apps before ??? One possible couse is ClassLoader, but why it has worked with my previous apps ?
[
]When I use FileInputStream JOGL files are found, but I can’t copy them withoud breaking. Dll’s are being copied to {java_home}/bin/, they have same size as oryginal dll’s (sources), but they are broken in some way - I get this error:


   java.lang.UnsatisfiedLinkError: C:\Program Files\Java\j2re1.4.2_05\bin\jogl.dll: Nieprawid³owy dostêp do komórki pamiêci (Invalid access to memory location)
      at java.lang.ClassLoader$NativeLibrary.load(Native Method)
      at java.lang.ClassLoader.loadLibrary0(Unknown Source)
      at java.lang.ClassLoader.loadLibrary(Unknown Source)
      at java.lang.Runtime.loadLibrary0(Unknown Source)
      at java.lang.System.loadLibrary(Unknown Source)
      at net.java.games.jogl.impl.NativeLibLoader$1.run(NativeLibLoader.java:60)
      at java.security.AccessController.doPrivileged(Native Method)
      at net.java.games.jogl.impl.NativeLibLoader.<clinit>(NativeLibLoader.java:46)
      at net.java.games.jogl.impl.GLContext.<clinit>(GLContext.java:50)
      at net.java.games.jogl.impl.windows.WindowsGLContextFactory.createGLContext(WindowsGLContextFactory.java:82)
      at net.java.games.jogl.GLCanvas.<init>(GLCanvas.java:70)
      at net.java.games.jogl.GLDrawableFactory.createGLCanvas(GLDrawableFactory.java:150)
      at net.java.games.jogl.GLDrawableFactory.createGLCanvas(GLDrawableFactory.java:118)
      at net.java.games.jogl.GLDrawableFactory.createGLCanvas(GLDrawableFactory.java:85)
      at pw.mchtr.book.animation.Animation.init(Animation.java:46)
      at sun.applet.AppletPanel.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)
   

[]I can’t use JarInputStream for jogl.jar - calling jarInputStream.getManifest() couses NullPointerException to be thrown (manifest is null), and copying the jar with just calling getNextJarEntry ends with ZipException: invalid entry size.
[
]When I copy jogl.jar using FileInputStream read() method, i get a jogl.jar with 0 bytes size :-[ I copy bytes until read return -1…
[*]Adding installer as an extension to applet does not help either - an exception is being throw when trying to run installer:

sun.misc.ExtensionInstallationException: Optional package installer is unsigned. (signatures missing or not parsable)
      at sun.plugin.extension.ExtensionInstallationImpl.verifyJar(Unknown Source)
      at sun.plugin.extension.ExtensionInstallationImpl.access$100(Unknown Source)
      at sun.plugin.extension.ExtensionInstallationImpl$1.run(Unknown Source)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.plugin.extension.ExtensionInstallationImpl.installExtension(Unknown Source)
      at sun.misc.ExtensionDependency.installExtension(Unknown Source)
      at sun.misc.ExtensionDependency.checkExtension(Unknown Source)
      at sun.misc.ExtensionDependency.checkExtensions(Unknown Source)
      at sun.misc.ExtensionDependency.checkExtensionsDependencies(Unknown Source)
      at sun.misc.URLClassPath$JarLoader.parseExtensionsDependencies(Unknown Source)
      at sun.misc.URLClassPath$JarLoader.getClassPath(Unknown Source)
      at sun.misc.URLClassPath.getLoader(Unknown Source)
      at sun.misc.URLClassPath.getResource(Unknown Source)
      at java.net.URLClassLoader$1.run(Unknown Source)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(Unknown Source)
      at sun.applet.AppletClassLoader.findClass(Unknown Source)
      at java.lang.ClassLoader.loadClass(Unknown Source)
      at sun.applet.AppletClassLoader.loadClass(Unknown Source)
      at java.lang.ClassLoader.loadClass(Unknown Source)
      at sun.applet.AppletClassLoader.loadCode(Unknown Source)
      at sun.applet.AppletPanel.createApplet(Unknown Source)
      at sun.plugin.AppletViewer.createApplet(Unknown Source)
      at sun.applet.AppletPanel.runLoader(Unknown Source)
      at sun.applet.AppletPanel.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)

I signed it of course :slight_smile:

Installers copy method:

jButton1.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent event)
      {
        Thread t = new Thread()
        {
          public void run()
          {
            String javahome = System.getProperty("java.home");
            String fileName;
            try
            {
              switch (jComboBox1.getSelectedIndex())
              {
                case 0:
                  fileName = "jogl-natives-linux.jar";
                case 1:
                  fileName = "jogl-natives-macosx.jar";
                case 2:
                  fileName = "jogl-natives-solsparc.jar";
                case 3:
                  fileName = "jogl-natives-win32.jar";
                default :
                  fileName = "jogl-natives-win32.jar";
              }
              //java.net.URL url = getClass().getResource("/lib/" + fileName);
              InputStream is = new FileInputStream("lib/" + fileName);
              ProgressMonitorInputStream pm = new ProgressMonitorInputStream(jPanel3, "Kopiowanie bibliotek natywnych", is);
              JarInputStream jis = new JarInputStream(pm);
              FileOutputStream fos = null;
              JarEntry je = null;
              byte[] dll = new byte[0];
              while ((je = jis.getNextJarEntry()) != null)
              {
                if (je.getName().equalsIgnoreCase("jogl.dll"))
                {
                  dll = new byte[(int)je.getSize()];
                  jis.read(dll);
                  fos = new FileOutputStream(javahome + File.separator + "bin" + File.separator + "jogl.dll");
                  fos.write(dll);
                  jis.closeEntry();
                  fos.close();
                }
                else if (je.getName().equalsIgnoreCase("jogl_cg.dll"))
                {
                  dll = new byte[(int)je.getSize()];
                  jis.read(dll);
                  fos = new FileOutputStream(javahome + File.separator + "bin" + File.separator + "jogl_cg.dll");
                  fos.write(dll);
                  jis.closeEntry();
                  fos.close();
                }
              }
              //url = getClass().getResource("/lib/jogl.jar");
              is = new FileInputStream("lib/jogl.jar");
              pm = new ProgressMonitorInputStream(jPanel3, "Kopiowanie bibliotek Javy", is);
              jis = new JarInputStream(pm);
              fos = new FileOutputStream(javahome + File.separator + "lib" + File.separator + "ext" + File.separator + "jogl.jar");
              JarOutputStream jos = new JarOutputStream(fos);
              while ((je = jis.getNextJarEntry()) != null)
              {
                jos.putNextEntry(je);
                jis.closeEntry();
              }

              fos.close();
              jis.close();
            }
            catch(Exception e)
            {
              e.printStackTrace();
              JOptionPane.showMessageDialog(null, e.getMessage());
            }
          }
        };
        t.start();
      }
    });

I really want to allow users to just open the website in a browser and watch JOGL in action… Must I switch to JNLP ?

HELP ! :o

Ps. If you want some additional info or source code for installer, I will send it to you or post it here.

Thanks for help !
Maciek

I think I got it :slight_smile: It seems that without BufferedInputStream some bytes were lost (why ??? don’t ask me ::)). I will test it to see if it really works (crossing fingers here ;)). If so I’ll put some info here.

At last ! Victory is mine !

Code is very simple, only one thing is tricky - dll’s are broken when copying them from original jars. It wasn’t the problem with absence of BufferedInputStream, but with reading form jars. I made a jar containing libraries for every system (bla bla bla … for those of you who had done it already ;)) and jogl.jar, and it works. The rest is like in previous post, java plug-in extension… and so on :wink: If more info is required - I can put the source code and installer on my site, so you can download it.

Ps. I checked installer locally and in an applet.
Ps2. Other problems were obviously my mistakes ::slight_smile:

Blast !
Forgot about three things:

[] Will it be enough when I put BSD license for Jogl in the jar with the installer or should I display it in installer itself ?
[
] Owners of the license - athomas, djp, kbr - should I use nicknames or ask athomas, djp, kbr for their real names ?
[*]Are the directories, where I copy files, the same in MacOSX or Solaris as in Windows ? I can check installer on Linux but not on Solaris nor on Mac :-/

Hi Maciek,

I am very interested in your sample. Can I know your website and download your source code about JOGL installer?

Thanks

You’ve made the newbie mistake of asuming InputStream.read(byte[]) will read the whole byte array. It don’t. It only reads some bytes. How many is returned by the function. I suggest you wrap the stream in a DataInputStream and use the readFully function. Read the javadoc for further info.

For (1), I don’t think it’s necessary to display the license; just include it and maybe a pointer to it in the documentation. For (2), don’t worry about the individual user names; Sun Microsystems is the copyright holder. For (3), I don’t know whether you’re talking about the directories in the JOGL distribution or the destination directories on disk. If the former, the JOGL distribution is structured the same way on all platforms. If the latter, I think you need to put extension jars and .jnilib files into /Library/Java/Extensions but I don’t know for sure.

there are 3 default directories for java extensions on OS X



~/Library/Java/Extensions/         # you should probably use this directory as it is for a specific user
/Library/Java/Extensions/          # this is the systemwide extension directory
/System/Library/Java/Extensions/   # this is for apple stuff only


i experienced some problems in the past when there where the same extensions installed in different directories.

On OS X you should consider simply keeping the JOGL jars and native libs in the Application Bundle. Assuming you use an application bundle for OS X, which would be the most OS X - like way to distribute your application to Mac users.

If you keep the library files inside the app bundle then there is no possibility of different versions of the library causing problems for different applications.

Maybe when JOGL is a little more mature it will be more appropriate to put it in the Extensions folder.

since we are talking about applets here, the application bundle structure is no real option. i think it s a good idea to install the libraries on the client machine, as you only need to do that once and not everytime you load an applet.

i always found the JSyn installer a pretty neat eyample – http://www.softsynth.com/jsyn/plugins/

i m really not sure about that. what is the search order for the default library paths? i didn t find any pointers on the apple website. as i said, i had problems with that in the past and it can definitely lead to confusion on a machine that is actually used by more than one user.

I have been following this discussion and others like it with great interest. It seems Java Webstart is not for everyone; some of us would like to be able to use JOGL in applets, and this sounds to me like exactly what is needed. At the very least, I require something that will work on the Windows and Mac OS. Can you share your installer code, or point me to a location where I can get more information?
Many thanks.