Access classes from package - java

I'm developing an android test app and i'm going to access all internal class of android.view package. android.view is a package that is present in jar file. I tried by loading package name but it doesn't display the classes if any one tried
this already, please help.
Here's what I tried so far:
public static void main() throws ClassNotFoundException{
Class o =Class.forName("android.view");
Class[] C=o.getDeclaredClasses();
for(int i=0;i<C.length;i++) {
Classname = C[i].getName();
ClassesDisplayActivity.your_array_list3.add(Classname);
Log.i("Ramu","classname "+ C[i].getName());
}
}
}

It is not possible to determine at runtime all of the classes that are in a package using a standard class loader.
You might have some luck with this library though:
https://code.google.com/p/reflections/

Package is not a class. You cannot call Class.forName() for package and access classes that belong to class using getDelcaredClasses().
I do not know what do you really need, so I'd recommend you to explain this in separate question. probably you will receive better solutions.
However if you really need this you have to do the following:
Get your classpath by calling System.getProperty(java.class.path)
split this property to its elements by colon
iterate over the list and read each resource. If resource is jar you can use ZipInputStream, if it is a directory use File class.
filter list of resources you got at #3.
Fortunately you can use 3rd party library named Reflections that helps you to do all this without writing code.

Related

How to load a java class outside the classpath?

I have a program where I want the user to be able to choose a .java class file from the file system, and then have that class loaded into the program.
I'm using a JFileChooser to allow the user to select a file. Then, I tried converting that file to a URL, and using a URLClassLoader to load the class (as suggested by these answers).
The problem is that, when I want to use the loadClass() method, I don't know the "full class name" of the class (e.g. java.lang.String). So, I don't know how to make this method work. Is there a way to get this class name? Or is there another way to do this?
Here is a sample of my code:
// Open the file chooser
JFileChooser fileChooser = new JFileChooser();
fileChooser.showOpenDialog(null);
File obtainedFile = fileChooser.getSelectedFile();
// Create the class loader from the file
URL classPath = obtainedFile.toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[] {classPath});
// Get the class from the loader
Class<?> theClassIWant = loader.loadClass("the file name"); // What do I put here??
Load a single class file is generally completely useless. Said class file isn't alone; it has more class files that are relevant. Even if you think 'nah, there is just one source file, do not worry about this', note that a single java file can easily generate multiple class files.
Thus, two options:
Don't load class files. Load jar files.
Use the usual mechanisms (META-INF/services or META-INF/MANIFEST.MF) to put some sort of class name in there so you know what to load. Then create a new classloader with the provided jar, load the manifest, figure out the main class, load that, and run it.
Attempt to determine the 'root' for the loaded class file and include that on the classpath.
This is quite difficult - the problem is, to 'load' a class file you need to tell the loader what the fully qualified name is of that class before it is loaded. But how do you know the fully qualified name? You can surmise the class name from the file (not quite always true, but usually), but the package is a more difficult issue.
You can open the class file yourself as a binary stream and write a basic class file format parser to get the fully qualified class name. Easy for an experienced java programmer. Quite tricky for someone new to java (which I gather you are, if you think this is a good idea).
You can also use existing tools to do this, such as bytebuddy or asm.
Finally, you can try a spaghetti-at-the-wall method: Keep travelling up the directory until it works. You know it isn't working if exceptions occur.
For example, to load C:\MyDir\Whatever\com\foo\MyApp.class, You first try creating a new classloader (see the API of URLClassLoader which is part of core java) using as root dir C:\MyDir\Whatever\com\foo, and then you ask it to load class MyApp.
If that works, great (but usually trying to load package-less classes is simply a non-starter, you're not supposed to do that, the CL API probably doesn't support it, intentionally, there is no fixing that).
If it doesn't, instead try C:\MyDir\Whatever\com, and load class foo.MyApp. If that doesn't work, try C:\MyDir\Whatever and load class com.foo.MyApp, and so on.
The considerable advantage is, if there is another class sitting right next to MyApp.class, and MyApp needs it, this will work fine.
You'll need to write a while loop (traversing the path structure using Paths.get and p.getParent()), catch the right exception, manipulate the path into the class name (using .replace and +), and, of course, create a class loader (URLClassLoader), load classes with it (invoke loadClass), and if you intend on running it, something like thatClass.getConstructor().newInstance() and then thatClass.getMethod("someMethod", String.class, /* all the other args here */).invoke(theInstanceYouJustMade, "param1", /*all other params */) to actually 'run' it, more to be found in the java.lang.reflect package.

Java with Beanshell to access fields and object with clean code

1). I know how to access the java fields and object in beanshell from my question Use java class fields in beanshell. However, it is not so clean way to implement as I need to first set the java variable in beanshell and then I can use it. However, in Jmeter it provides very clean way of using maps in beanshell similar way as we do in java, but JMeter has developed it's know library (class) which helps to access get/put methods for maps. I want to achieve similar way to access Map in beanshell.
I have checked JMeter for more information and I want to know that, I have created user define variable temp and assign value error, now in BSF process I just write a line vars.put('Name','temp Value') and it has updated value for temp variable. So, the question is I have not created JMeterVariables object vars but still beanshell allows to update values in map without setting any values as mention in your answer. I want to know how this works, need more depth information.
2). I have created my own class in java and in beanshell I am importing this class but it is giving Command not found: BSClass() below is the entire code
Java class
package test;
public class BSClass {
public void BSCMethod(){
System.out.println("I am from BSClass method BSCMethod");
}
}
sample.bsh
import test.BSClass;
c=BSClass();
c.BSCMethod();
print("I am from BeanShell Script");
Calling sample.bsh file java class
package test;
import java.io.FileNotFoundException;
import java.io.IOException;
import bsh.*;
public class DynamicVariable {
public static void main(String[] args) throws FileNotFoundException, IOException, EvalError {
new bsh.Interpreter().source("\\src\\test\\sample.bsh");
}
}
Note:
I don't need help in JMeter, it is to use in core java and beanshell.
All the files are in my project.
BSClass.class is under bin folder of my project
I would appreciate your inputs
In Beanshell you can add any Object you want including a Map
In JMeter, JMeterVariables is special implementation of Map that is added to Beanshell Interpreter before evaluate and also special Object as JMeterContext is added which even includes JMeterVariables inside. Code:
JMeterContext jmctx = JMeterContextService.getContext();
JMeterVariables vars = jmctx.getVariables();
try {
bshInterpreter.set("ctx", jmctx);//$NON-NLS-1$
bshInterpreter.set("Label", getName()); //$NON-NLS-1$
bshInterpreter.set("prev", jmctx.getPreviousResult());//$NON-NLS-1$
bshInterpreter.set("props", JMeterUtils.getJMeterProperties());
bshInterpreter.set("vars", vars);//$NON-NLS-1$
In your case with map you can do similar as you describe in comment:
bshInterpreter.set("myMap", javaMyMapObject);"
Then in Beanshell get the specific key from map:
myMap.get("aField");
To create class you should use new keyword, call:
c= new BSClass();
instead of c=BSClass();
If you create your own class, Class should be inside jar in relevant package .
The jar should be located in lib folder and not in bin folder, see JMeter's getting started:
Any jar file in such a directory will be automatically included in
user.classpath, jar files in sub directories are ignored. The given
value is in addition to any jars found in the lib directory. All
entries will be added to the class path of the system class loader and
also to the path of the JMeter internal loader.

How to write an import statement to refer to a java class in a jar?

How can I refer to a Java class in stdlib1.jar when the directory structure is like this? How to write the import statement?
I want to call a method under stdlib1.jar, I have configured it.
The classes are in the default package. According to this answer, it is not possible to import classes from the default package. So, they have to be moved to another package or you have to use reflection.
You call a method from a class and not from a package.
You don't need to specify the jar when you call a method from a class belonging to it. Which matters is your jar is in the classpath
In your screenshot if the lib makes part of the classpath folders, you can import and use classes from it in your code.
Here the classes of your jar use the default package (no package name) which seems weird for a third-party library. Default package is not recommended since it doesn't allow to naturally reference and use the classes of the archive from the client code.
I am not sure you are using the correct version of the jar. Look at that :
http://grepcode.com/snapshot/repo1.maven.org/maven2/com.googlecode.princeton-java-introduction/stdlib/1.0.1
This contains classes in the edu.princeton.cs package :
With package, you could declare this :
For example :
You could create a class like that and use BinaryIn like that:
package main;
import edu.princeton.cs.BinaryIn;
public class MyClass(){
public static void main(String args[]){
BinaryIn in = new BinaryIn();
}
}

Class reference is taken from different jar

There are some classes used in a java program referred from abc package from xyz.jar. The package is imported in the java file.
Also the same class is in other lmn.jar.
So if I delete the jar file from the project, i should be getting the error.
But the class compiles and takes the class from the other lmn.jar.
Eg.
weblogic.jdbc.oci.Blob is a class in weblogic.jar
But if i delete weblogic.jar, it takes it from java.sql.Blob.
I don't want this to happen, the program should display error.
In such a case you can use fully qualified name of class, which will include package name. For example, instead of:
Blob blob = new Blob();
You can write:
weblogic.jdbc.oci.Blob blob = new weblogic.jdbc.oci.Blob();
When importing a class you are also defining the package. So when you import "weblogic.jdbc.oci.Blob" and remove this class from classpath it will not automatically import it from a different package unless you change the import statement as well.
Some IDEs might automatically try to resolve classes and add the missing import statements. Maybe check that.
For one of the case try to use the entire path, ie
For example if you need Blob from weblogic.jar
then try to call weblogic.jdbc.oci.Blob bl = ...

How to instantiate a class without knowing its package?

I have an Eclipse project (MainProject) and it references another Eclipse project (ReferencedProject). MainProject also references a JAR file (ReferencedJar). This ReferencedJar's file name is known. I also know there is a class (ReferencedClass) in ReferencedJar, but I don't know in what package ReferencedClass is because the package path is not known beforehand.
I need to instantiate ReferencedClass in ReferencedProject using reflection. How can I do this? And will the solution be okay when the project is packaged to a its standalone jar outside Eclipse?
The reason for this question is; The ReferencedJar is file generated by a modeller application. It generates java classes for your model and puts them into ReferencedJar. The user can choose which package the classes it generates will be put into. But the class names are always the same. MainProject is project that will include this generated jar, but ReferencedProject (a framework) also needs to instantiate a class in this generated jar. Hope this makes the question more clear.
Thanks in advance
Edit: Actually I have an idea but don't know how to implement it. Because I know the name of ReferencedJar file, I could access it on runtime and check all the classes it contains. Then I can find the matching class by name comparison. But how can I access the ReferencedJar on runtime?
As long as the class you need is in the class path, you can get a reference to it by invoking Class.forName(String className)
String className = "WhatEver";
String packageName = "some.package";
Class<?> c = Class.forName(packageName + "." + className);
If you don't know the package name, however, and there's no way to get it from a configuration file, I would recommend using a library like reflections to scan the class path and find the relevant class.
You can not instantiate a class you if do not know its package

Categories