plugin property

Hello

I am having problems to load the plugins directory from a specific location. If I put a “controller” dir with the plugins in it in the directory from where my test is launched, all works fine. But if I use

java -Djinput.controllerPluginPath=c:/jinput JInputTest

I get a NullPointerException. But it should work, right? What am i doing wrong??

Thanks for the help 8)

Hi
yes it should, but to help work out whats going wrong we will need more info, like the null pointer stack trace and any program output would be good :slight_smile:

Thanks

Endolf

Sorry about the lack of information :-[

I am trying to run the KeyBoardTest class I found somewhere in this forum.


java.lang.NullPointerException
      at KeyboardTest.keyboardupdate(KeyboardTest.java:30)
      at KeyboardTest.<init>(KeyboardTest.java:23)
      at KeyboardTest.main(KeyboardTest.java:7)
Exception in thread "main" 

This exception is raised whenever I run “java” with or without the “-D” option.

Sure this exception alone doesn’t help much, so here is the line that is causing the exception:


kb.poll();

It looks like that no controller was found, so the “kb” doesn’t get to be initialized.

I am starting with jinput, so maybe the problem is obvious…
I am trying to make this to work so I feel secure to use jinput in my project

I tried it too, with my controller dir containing both dxinput.jar and dxinput.dll. The dxinput plugin seems to be detected but I get another exception :


Scanning jar: dxinput.jar
Examining file : META-INF/
Examining file : META-INF/MANIFEST.MF
Examining file : net/java/games/input/DirectInputAxis.class
Examining file : net/java/games/input/DirectInputDevice.class
Examining file : net/java/games/input/DirectInputEnvironmentPlugin.class
Found candidate class: net/java/games/input/DirectInputEnvironmentPlugin.class
java.lang.NoClassDefFoundError: IllegalName: net/java/games/input/DirectInputEnvironmentPlugin
      at java.lang.ClassLoader.preDefineClass(ClassLoader.java:459)
      at java.lang.ClassLoader.defineClass(ClassLoader.java:598)
      at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
      at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
      at java.net.URLClassLoader.access+100(URLClassLoader.java:56)
      at java.net.URLClassLoader+1.run(URLClassLoader.java:195)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
      at net.java.games.util.plugins.Plugins.processJar(Plugins.java:115)
      at net.java.games.util.plugins.Plugins.scanPlugins(Plugins.java:88)
      at net.java.games.util.plugins.Plugins.<init>(Plugins.java:76)
      at net.java.games.input.DefaultControllerEnvironment.scanControllersAt(DefaultControllerEnvironment.java:199)
      at net.java.games.input.DefaultControllerEnvironment.scanControllers(DefaultControllerEnvironment.java:189)
      at net.java.games.input.DefaultControllerEnvironment.access$000(DefaultControllerEnvironment.java:58)
      at net.java.games.input.DefaultControllerEnvironment$1.run(DefaultControllerEnvironment.java:109)
      at java.security.AccessController.doPrivileged(Native Method)
      at net.java.games.input.DefaultControllerEnvironment.getControllers(DefaultControllerEnvironment.java:107)

Could someone explain me what that line means ?

java.lang.NoClassDefFoundError: IllegalName: net/java/games/input/DirectInputEnvironmentPlugin

Hi
Ok, I’ve just got a fresh binary of jinput, on a machine that untill 20 minutes ago didn’t even have java on it, the following is my input and output showing the jinput.controllerPluginPath working.

Hope it helps

Endolf

C:\Jeremy\jinput-1.0beta-bin-windows\coreAPI>java -cp bin\jinput.jar;lib\jutils.
jar -Djinput.controllerPluginPath=src\tests\controller net.java.games.input.test
.ControllerReadTest
Scanning jar: dxinput.jar
Examining file : META-INF/
Examining file : META-INF/MANIFEST.MF
Examining file : net/
Examining file : net/java/
Examining file : net/java/games/
Examining file : net/java/games/input/
Examining file : net/java/games/input/DirectInputAxis.class
Examining file : net/java/games/input/DirectInputDevice.class
Examining file : net/java/games/input/DirectInputEnvironmentPlugin.class
Found candidate class: net/java/games/input/DirectInputEnvironmentPlugin.class
Adding class to plugins:net.java.games.input.DirectInputEnvironmentPlugin
Examining file : net/java/games/input/DirectInputKeyboard.class
Examining file : net/java/games/input/DirectInputMouse$BallAxis.class
Examining file : net/java/games/input/DirectInputMouse$BallImpl.class
Examining file : net/java/games/input/DirectInputMouse$ButtonImpl.class
Examining file : net/java/games/input/DirectInputMouse$ButtonsImpl.class
Examining file : net/java/games/input/DirectInputMouse.class
Examining file : net/java/games/input/DirectInputRumbler.class
Axis count = 2
Axis count = 2
Axis count = 124

[quote]Could someone explain me what that line means ?

java.lang.NoClassDefFoundError: IllegalName: net/java/games/input/DirectInputEnvironmentPlugin

[/quote]
That looks like an error with 1.5 beta JDK, try it on 1.4.

There was a thread somewhere in this forum about it.

HTH

Endolf

Edit: it’s 2/3 of the way down this thread.

Thanks endolf ! I think I mixed two JInput nightly builds, and one had still that 1.5 bug.

I cleansed the evil out of my machine :slight_smile: and now it works fine.

I’ve just tried to run as you did. It worked! :slight_smile:
But them I changed the path to the plugins to an absolute dir, and it stoped working. Is this a bug or is an intended behavior?

No, absolute paths won’t work. I opened the sources and currently, JInput scans for plugins :

  • JAVA_HOME/lib/PLUGIN_PATH
  • USER_DIR/PLUGIN_PATH

where JAVA_HOME is System.getProperty(“java.home”), USER_DIR is System.getProperty(“user.dir”) and PLUGIN_PATH is System.getProperty(“jinput.controllerPluginPath”) or “controller”.

Supporting absolute paths would require some trivial changes to net.java.games.input.DefaultControllerEnvironment in the scanControllers and scanControllersAt methods.

Hi
Supporting absolute paths isn’t high on the priority list in my own opinion as when you then deploy your application the absolute path will probably be different on the machines it’s installed on, if you want to make the changes and submit a patch thats not a problem, if you raise a bug on the jinput issue tracker you can then submit the patch to that too and someone will stick it in cvs.

Cheers

Endolf

[quote]Supporting absolute paths isn’t high on the priority list in my own opinion as when you then deploy your application the absolute path will probably be different on the machines it’s installed on, if you want to make the changes and submit a patch thats not a problem, if you raise a bug on the jinput issue tracker you can then submit the patch to that too and someone will stick it in cvs.
[/quote]
I am fine with the current system : absolute paths wouldn’t add much to JInput.

Furthermore, my first tests raised an error when loading a native lib and I am not enough experienced with dynamic classloading to correct it at the moment. I’ll investigate it if I really need this functionality, but it is not my priority either.

Cool
Thats my take on it too. To allow the native lib loading you need to update the java.library.path property, i think that the plugin architecture adds it for you, hence not having to do it manually at run time. As you said though, I don’t think it will add much, most apps will want the plugin path somewhere under the root of the project.

Cheers

Endolf

In fact the JVM was complaining that the library path was relative, not absolute. The error is in the findLibrary method of PluginLoader : instead of

String libpath = parentDir.getPath() + File.separator + System.mapLibraryName(libname);

it should be something like :

String libpath = parentDir.getAbsolutePath() + File.separator + System.mapLibraryName(libname);

Well there are several other changes involved to support correctly absolute paths, I’ll post the code here so that it can be tested before submitting an official RFE + patch ;D

All these changes are made in net.java.games.input.DefaultControllerEnvironment.

  1. replace method scanControllers() with

    private void scanControllers() {
        String pluginPathName = System.getProperty("jinput.controllerPluginPath");
        if(pluginPathName == null) {
            pluginPathName = "controller";
        }

        File[] dirs = getPotentialDirectories(pluginPathName);

      for(int i = 0; i < dirs.length; i++) {
            scanControllersAt(dirs[i]);
        }
    }

  1. replace method scanControllersAt(String path) with

    private void scanControllersAt(File file) {
        try {
            Plugins plugins = new Plugins(file);
            Class[] envClasses = plugins.getExtends(ControllerEnvironment.class);
            for(int i=0;i<envClasses.length;i++){
                try {
                    if (DEBUG) {
                        System.out.println("ControllerEnvironment "+
                            envClasses[i].getName()
                            +" loaded by "+envClasses[i].getClassLoader());
                    }
                    ControllerEnvironment ce = (ControllerEnvironment)
                        envClasses[i].newInstance();
                    addControllers(ce.getControllers());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

(this is exactly the same method, except that it handles directly Files)

  1. add the following methods

    private String[] getPotentialPaths(String pluginPathName) {
        String javaHomePath = System.getProperty("java.home") + File.separator + "lib" + File.separator + pluginPathName;
        String userDirPath = System.getProperty("user.dir") + File.separator + pluginPathName;
        String rawPath = pluginPathName;

        String[] allPaths = { javaHomePath, userDirPath, rawPath };

        return allPaths;
      }


    private File[] getPotentialDirectories(String pluginPathName) {
        String[] paths = getPotentialPaths(pluginPathName);
        File[] dirs = null;

        if(paths.length > 0) {
            File[] allDirs = new File[paths.length];
            int validDirCount = 0;

            for(int i = 0; i < paths.length; i++) {
                try {
                    File f = (new File(paths[i])).getCanonicalFile();

                    if(f.exists()) {
                        boolean duplicated = false;

                        for(int j = 0; j < validDirCount; j++) {
                            duplicated |= f.equals(allDirs[j]);
                        }

                        if(! duplicated) {
                            allDirs[validDirCount] = f;
                            validDirCount ++;
                        }
                    }
                }

                catch(IOException ioe) {
                    ioe.printStackTrace();
                }
            }

            dirs = new File[validDirCount];
            System.arraycopy(allDirs, 0, dirs, 0, validDirCount);
        }

        else {
            dirs = new File[0];
        }

        return dirs;
    }

getPotentialPaths constructs the paths to be explored.
getPotentialDirectories makes sure that no directory will be searched twice by comparing files (trying to load the same library several times generates errors).

[EDIT] Sorry, my code indentation got screwed up by this damn forum >:( If you are interested, I can mail you the file.

Hi
Dealing with files direct can screw up webstart if I recall, and that is far more useful than using absolute paths :slight_smile:

Endolf

Good point :slight_smile:

However I think absolute paths could be useful during the testing phase, when you work with several plugin directories. In a game release the plugin directory would be under the root, as you pointed out before.

As far as I’m concerned, I put all jogl/joal/jinput stuff in my jre/lib and jre/lib/ext directories, because I am too lazy to add them to the classpath manually ;D

So at the moment I don’t need that feature, but the code is here if someone want to test it or to include it in JInput.