P
P
plishas2014-08-12 17:09:32
git
plishas, 2014-08-12 17:09:32

How to read the list of classes from a package that is in the same jar file as the program?

A java program is being written that must process pictures using operators.
Operator classes are read dynamically from one package in the program into an array of classes.
The method for reading works in the console but does not work in the jar file...

public class PackageClassList {
  public static List<Class<?>> getClasses( String pack ) throws Exception{
    	    	ClassLoader cl = PackageClassList.class.getClassLoader();
    	        String packageDir = pack.replaceAll("[.]", "/");
            	List<Class<?>> classes = new ArrayList<Class<?>>();
    	    	URL upackage = cl.getResource(packageDir);
    	    	InputStream in = (InputStream) upackage.getContent();
    	    	BufferedReader br = new BufferedReader(new InputStreamReader(in));
    	    	String line = null;
    	    	while ((line = br.readLine()) != null) {
    	    	    	if(line.endsWith(".class"))
    	    	    	classes.add(Class.forName( pack+"."+line.substring(0,line.lastIndexOf('.'))));
    	    	}
    	    	return classes;
    	}
}

actually, this is a training project - I'm doing it in parallel with preparing for the OCPJP.
I want to do it quickly and learn something ...
maybe I can implement it somehow differently?
would you recommend anything?
my idea was this - I write operators for myself, put them in the oparators package. Operators inherit from the AbstractOperator abstract class.
The program automatically reads the operators package and loads the classes from there into the array. Make a dropbox from the array, distance operators and apply them, polymorphism, everything is beautiful, etc.
Then I want to pack it into an executable array and send it to someone ...
so that a person without fuss, launches jar and looks, and does not unpack the archive, looking for a batch file ...
I want to do everything in Eclipse and not bother with copying and packing statements... setup, configuration...
compiled, packaged and that's it.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
D
devian3000, 2016-06-07
@Tispartaaaa

First, push the changes to the correct branch (in the remote repository, check that all changes have been committed in task1, i.e. that the last commit has passed, otherwise there is a chance of losing all the work)
git push origin task1
Then on the master, get all the changes from the remote turnip
git checkout master
git fetch --all
git rebase origin/master
Fetch changes and force them back to master
git reset --hard HEAD~1
git push origin master -f

R
Ruslan Lopatin, 2014-08-12
@lorus

There is no such way. Unless some undocumented.
Instead, I recommend using annotation processing, at compile time for your project, make a list of classes and put it in a separate file. The default location for such files is in META-INF/services/<interface name>. You can load instances of classes from this list using the ServiceLoader class .
Well, or manually make this list.

V
vlad20012, 2014-08-14
@vlad20012

More as possible. annotation processing is a good thing, not a bit of an answer to the question. Let's assume there are reasons not to use it. Then usually the code source, i.e. jar archive with classes is taken as a file, a list of files is read from it, as from a zip archive, and if the file name matches a certain template (for example, it is in a certain package), a class with the same name is loaded. You can get code source something like this:
Although, this will only get the location of the current class. All linked URLs can be obtained like this:
And then use ZipFile, read the Entry list, check for pattern matching.
You can use the same annotations instead of the class name template, but then you have to read them through ASM without loading the class. So see which is easier.
This method is considered not very good, because classes can be loaded not only from jar archives. At a minimum, you need to consider loading from a directory, but in theory, classes can be loaded from anywhere, and code source may well be absent, i.e. getCodeSource() will return null. However, many people use this method. For example, log4j loads plugins in this way, but annotation processing is also present there, no one canceled the combination of approaches.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question