How can you set the search path for JavaToRascal from Java - java

We tried to import a test rascal module and a module from the standard library using JavaToRascal.
The test module is stored in C:\Users\Klemens\workspace\RascalInterop\src\MyTest.rsc and contains:
module MyTest
Te java code containing the JavaToRascal invocation is as follows:
import java.io.PrintWriter;
import java.net.URISyntaxException;
import org.rascalmpl.interpreter.JavaToRascal;
import org.rascalmpl.interpreter.load.IRascalSearchPathContributor;
import org.rascalmpl.interpreter.load.StandardLibraryContributor;
import org.rascalmpl.interpreter.load.URIContributor;
import org.rascalmpl.uri.URIUtil;
public class RascalInterop {
public static void main(String[] args) throws URISyntaxException {
JavaToRascal j2r = new JavaToRascal(new PrintWriter(System.out), new PrintWriter(System.err));
IRascalSearchPathContributor modulePath = new URIContributor(URIUtil.createFileLocation("C:\\Users\\Klemens\\workspace\\RascalInterop\\src\\MyTest.rsc"));
j2r.getEvaluator().addRascalSearchPathContributor(modulePath);
try {
j2r.eval("import MyTest;").toString(); // Could not import module MyTest: can not find in search path
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
j2r.getEvaluator().addRascalSearchPathContributor(StandardLibraryContributor.getInstance());
j2r.eval("import IO;").toString(); // null pointer exception
} catch (Exception e) {
System.out.println(e.getClass());
}
}
}
The print in the first try block that tries to import our MyTest.rsc module results in:
Could not import module MyTest: can not find in search path
?[Advice](http://tutor.rascal-mpl.org/Errors/Static/ModuleImport/ModuleImport.html)
The second import attempting to import the IO module from the standard library results in:
class java.lang.NullPointerException
Any ideas how to use properly set the search path from a Java program?
We tried to use j2r.getEvaluator().addRascalSearchPathContributor in various ways but did not succeed in loading a MyTest.rsc module from the given directory.

Despite that these API will change in the near future (due to the compilation process and related changes), here's an answer. Two answers actually, one for Rascal files and one for Java code that it needs
For Rascal:
j2r.getEvaluator().addRascalSearchPathContributor
What you used is the correct way of doing things. So if it did not work, please provide more code so we can diagnose what goes wrong. So where is your module? Is it in a jar file or a binary folder? If its in a jar, you need some additional wiring I'm glad to explain.
The Rascal search path is distinguished from the Classpath for Java classes which are used by Rascal. So you have different API for that. We use classloaders to find Java files (such that it also works for situations like OSGI bundles in Eclipse):
Evaluator x = ctx.getEvaluator();
x.addClassLoader(getClass().getClassLoader());
This will make sure that the class loader used to load the current class is also used to load the class linked mentioned in the Rascal file. Of course you can also provide other class loaders. Note that if the libraries you depend on are loaded via OSGI, make sure you get a classloader from a class that is in a bundle that has access to these classes. The simple case is when everything is in the same jar file, then any classloader will do.

I think you should change the path to refer to the src directory instead of the source file:
new URIContributor(URIUtil.createFileLocation("C:\\Users\\Klemens\\workspace\\RascalInterop\\src"));
Also: probably you should use forward slashes without C:\, so /Users/.../src
AFAIK The null pointer exception is expected, evaluating import returns null, and you try to call toString().

Related

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.

Java files with cyclic imports

I am trying to understand how javac deals with cyclic imports. After few attempts, I got the below code to be compiled:
package com.test.p1;
import com.test.p2.ClassP2;
public class ClassP1 {
public static void main(String[] args) {
System.out.println("ClassP1 loaded");
ClassP2.testP2();
}
}
And
package com.test.p2;
import com.test.p1.ClassP1;
public class ClassP2 {
public static void testP2() {
System.out.println("ClassP2 loaded");
}
}
When I compiled ClassP2.java first, I was expecting it to fail as ClassP1.java was not yet compiled and no class file was generated. Yet, it compiled ok, and generated ClassP2.class and ClassP1.class. Running ClassP1 worked fine as well.
Now my question is how did javac generate class file for ClassP1 when I only compiled ClassP2. And why does this not happen when cyclic reference is not there - i.e. when ClassP2 imports ClassP1, but ClassP1 does not import ClassP2 ?
I am still new to Java and trying to understand how compilation works.
There's nothing cyclic going on here. It sounds like you, along with a lot of other people, confuse import with class loading.
All the import statement does is allow you to use the short name to refer to a Java class in your code:
import java.sql.ResultSet;
public V find() {
ResultSet rs = null; // You can type ResultSet instead of java.sql.ResultSet
}
The import statement won't help you if the short name is ambiguous (e.g. java.util.Date and java.sql.Date in the same class).
The byte code for java.sql.ResultSet is not loaded into the JVM until your code needs it at runtime.
It is not a result of cyclic imports, it is a result of importing ClassP1 in ClassP2.java and javac being able to find the source for ClassP1 based on the arguments you passed to javac and the location from which you executed the command.
See the -sourcepath option in the docs for javac:
-sourcepath sourcepath
Specify the source code path to search for class or interface definitions. As with the user class path, source path entries are separated by semicolons (;) and can be directories, JAR archives, or ZIP archives. If packages are used, the local path name within the directory or archive must reflect the package name.
Note: Classes found through the class path may be subject to automatic recompilation if their sources are also found. See Searching For Types.

Access classes from package

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.

Java type cannot be resolved MIME type class

I know this is a common question asked but I've been searching and I've included the class into eclipse through the buildpath. I start to write the import statement and it autocompletes options for me so I know it's finding the class.
My problem is how come it's giving this error when I'm reading the docs and it says the constructor method is MimeUtil2() ?
http://www.jarvana.com/jarvana/view/eu/medsea/mimeutil/mime-util/2.1/mime-util-2.1-javadoc.jar!/eu/medsea/mimeutil/MimeUtil2.html#MimeUtil2()
package com.jab.app;
import java.io.File;
import eu.medsea.mimeutil.*;
public class CheckFileType {
private void GetMimeType(File filename){
MimeUtil2 test = new MimeUtil2(); //Produces the error saying java type cannot be resolved
}
I think you need to import
import eu.medsea.mimeutil.*;
According to the documentation, the type is eu.medsea.mimeutil.MimeUtil2
I ended up finding out that I was using the test-source.jar not the main jar file itself. The sourceforge page made the default as the source file instead of the main jar file.
It was buried inside of the files page.

getting full classpath from a class

I'm looking a utility method so that given a class will return the full classpath required to run this class externally. This means the jar the class is in as well as all jars (or folders) of classes that it uses.
UPDATE: there are tools that analyze .class files to find dependencies. This is not what I'm looking for. I'm looking for something that uses Java's reflection API on an already loaded class. I'll settle for something that analyzes byte code, if it goes recursively into classes it finds through the class loader
Reflection will not help you a lot for this one. You will need to analyse the byte code to find dependencies.
UPDATE:
Alright then. I am using a library that I made years ago, that you can download here.
The following code:
package classdep;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.jedo.classfile.ClassFile;
import org.jedo.classfile.ConstantPool;
public class Main {
public static void main(String[] args) {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
List<String> classes = new ArrayList<String>();
classes.add(args[0].replace('.', '/'));
for (int i = 0; i < classes.size(); ++i) {
String className = classes.get(i);
URL url = cl.getResource(className + ".class");
if (url == null) {
System.out.println("--- class not found " + className);
} else {
System.out.println(url);
ClassFile classFile = new ClassFile();
InputStream in = url.openStream();
try {
classFile.load(in);
} finally {
in.close();
}
ConstantPool cp = classFile.getConstantPool();
for (String name: cp.getClassNames()) {
if (!classes.contains(name)) {
classes.add(name);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Will give you all the dependencies of a class. When applied to org.jedo.classfile.ClassFile, it produces the following output:
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/ClassFile.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/ConstantPool.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/FieldInfo.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/MethodInfo.class
file:/D:/projects/casagrande/jedo/build/classes/org/jedo/classfile/AttributeInfo.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/File.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/FileInputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/DataInputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/StreamCorruptedException.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/FileOutputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/DataOutputStream.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/lang/StringBuilder.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/lang/StringBuffer.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/lang/Object.class
jar:file:/C:/Program%20Files/Java/jdk1.6.0_18/jre/lib/rt.jar!/java/io/IOException.class
...
Followed by a lot of system classes. You need to filter out system classes, and parse the other urls to extract either the .jar file if it is a jar: url, or the directory if it is a file: url.
I don't think this is possible. Certainly, the reflection APIs don't support it.
You can find out a classes classloader, but you cannot find out:
which of the classloader's possible JAR files and directories contained the class,
what the static dependencies of the class are, or
what the dynamic dependencies of the class are; e.g. what it or its dependants loaded using Class.forName().
Actually, this overstates things somewhat:
You can in theory figure out which classes came from which JARs if you can find out what the classpath is. There are possibly ways to dig this out of a classloader.
You can in theory figure out what a classes dependants are, but you been to dig around in the class'es bytecode file using (for instance) BCEL to find this out.
You can in theory figure out what was dynamically loaded if you are prepared to write your own classloader. It may be possible to link this back to the class that initiated the loading using some hairy analysis of the stack frames.
But this is all extremely complicated, and I'd expect it to be unreliable under certain circumstances.
There are cases when you cannot determine this prior to using your class.
This cannot always be known. For instance, a class can be dynamically created at run time and then loaded with a custom ClassLoader.
I do not believe Java stores this information.

Categories