0

Sorry I'm new here but I have and issue I'm hoping someone can help me solve.

This code runs perfect while in eclipse, but after compiled it say's:

java.lang.IllegalArgumentException: URI is not hierarchical

Any help would be appropriated, thanks!

public void loadMods(String pkg) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
    List<Class<?>> classes = getClasses(pkg);
    for(Class<?> c : classes) {
        for (Method m : c.getMethods()) {
            Object o = null;
            o = c.newInstance();
            if (m.getName().contains("load")) {
                m.setAccessible(true);
                m.invoke(o);
            }
        }
    }
}

public static List<Class<?>> getClasses(String pkg) {
    String pkgname = pkg;
    List<Class<?>> classes = new ArrayList<Class<?>>();
    File directory = null;
    String fullPath;
    String relPath = pkgname.replace('.', '/');
    URL resource = ClassLoader.getSystemClassLoader().getResource(relPath);
    if (resource == null) {
        throw new RuntimeException("No resource for " + relPath);
    }
    fullPath = resource.getFile();
    try {
        directory = new File(resource.toURI());
    } catch (URISyntaxException e) {
        throw new RuntimeException(pkgname + " (" + resource + ") invalid URL / URI.", e);
    } catch (IllegalArgumentException e) {
        directory = null;
    }
    if (directory != null && directory.exists()) {
        String[] files = directory.list();
        for (int i = 0; i < files.length; i++) {
            if (files[i].endsWith(".class")) {
                String className = pkgname + '.' + files[i].substring(0, files[i].length() - 6);
                try {
                    classes.add(Class.forName(className));
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException("ClassNotFoundException loading " + className);
                }
            } else {
                String pkgnamex = pkgname + '.' + files[i];
                List<Class<?>> classesx = new ArrayList<Class<?>>();
                File directoryx = null;
                String fullPathx;
                String relPathx = pkgnamex.replace('.', '/');
                URL resourcex = ClassLoader.getSystemClassLoader().getResource(relPathx);
                if (resourcex == null) {
                    throw new RuntimeException("No resource for " + relPathx);
                }
                fullPathx = resourcex.getFile();
                try {
                    directoryx = new File(resourcex.toURI());
                } catch (URISyntaxException e) {
                    throw new RuntimeException(pkgnamex + " (" + resourcex + ") invalid URL / URI.", e);
                } catch (IllegalArgumentException e) {
                    directoryx = null;
                }
                if (directoryx != null && directoryx.exists()) {
                    String[] filesx = directoryx.list();
                    for (int ix = 0; ix < filesx.length; ix++) {
                        if (filesx[ix].endsWith(".class")) {
                            String classNamex = pkgnamex + '.' + filesx[ix].substring(0, filesx[ix].length() - 6);
                            try {
                                classes.add(Class.forName(classNamex));
                            } catch (ClassNotFoundException e) {
                                throw new RuntimeException("ClassNotFoundException loading " + classNamex);
                            }
                        }
                    }
                }
            }
        }
    }
    return classes;
}
SoWhoYou
  • 3
  • 4
  • 2
    Possible duplicate of [Java Jar file: use resource errors: URI is not hierarchical](http://stackoverflow.com/questions/10144210/java-jar-file-use-resource-errors-uri-is-not-hierarchical) – SomeJavaGuy Oct 08 '15 at 06:54
  • 1
    Possible duplicate of [why my URI is not hierarchical?](http://stackoverflow.com/questions/18055189/why-my-uri-is-not-hierarchical) – Eduardo Yáñez Parareda Oct 08 '15 at 06:58

1 Answers1

0

When you run the code from within Eclipse it uses the compiled classes (by default in folder 'target'). However if you run the code from external normally you use a JAR file created by Eclipse.

And this problem arises when referencing something inside the JAR which is explained by the linked questions.

In short: URIs in the file system are syntactically correct. An URI referencing something into a JAR is no more a valid URI.

Sebastian
  • 395
  • 2
  • 7
  • Loading mods contained in the same JAR seems to be questionable. If you have optional modules there a better technologies to achieve that, for example OSGI or Service Provider. You can also try to use the ProtectionDomain but this is rather tricky and may fail due to security restrictions. – Sebastian Oct 08 '15 at 07:25
  • Ok I have finally found a way to do what I wanted to do, I just figured I would share with everyone, just in case someone down the road tries to do what I was doing and fails. Here is the source code for what I have got to work: https://github.com/SoWhoYou/breakcraft/blob/master/mod/ModLoader.java – SoWhoYou Oct 10 '15 at 07:28
  • Thanks for the provided code. Its too much to analyse it in a few minutes at a deeper level. No insult, but it looks problematic: 1 No JavaDoc 2 All methods are public but one modifies a member which changes behaviour of other methods => Calling the methods in different order may give different results 3) No private constructor to prevent accidental instantiation 4) Code could be shorter by using more API 5) Performance could probably be better by using Set instead of List 6) No tests. The code looks like being well-suited to pair programming – Sebastian Oct 12 '15 at 07:54
  • The link github.com/SoWhoYou/breakcraft/blob/master/mod/ModLoader.jav‌​a is broken :'-( – JN Gerbaux Jan 20 '17 at 13:31