Ant script to Find a jar file given the class name? - java

how to find the name of jar which contains the specific class through ant script?

We are using the following Ant code to find the jar containing our main class. It requires Ant 1.8+.
<whichresource class="${main.class}" property="main.class.url">
<classpath>
<fileset dir="${jar.dir}" includes="*.jar" />
</classpath>
</whichresource>
<pathconvert property="jar.file">
<url url="${main.class.url}" />
<regexpmapper from="jar:file:/(.*)!.*" to="\1" />
</pathconvert>
<echo>Jar file containing main class: ${jar.file}</echo>
I hope this answers your question.
Maarten

Try jarscan . It is a commandline java tool, it should be easy if you want to integrate it through ant also.

I think this problem can be better solved by a 1-line (ok, 5-line) C-shell script. Suppose you are trying to find a list of jar files in some directory that contain a certain file. Try this at your csh prompt:
% cd directory_where_your_jar_files_reside
% set f2Search = filename_you_are_looking_for
% foreach jarFile (*.jar)
? (jar tvf $jarFile | grep $f2Search > /dev/null) || echo $jarFile
? end
You can obviously concat the output to some other file if required. This is a Unix solution, dunno how to do this on Windows, sorry. Apologies for not answering the Ant question, but others have answered it already. Hope this helps, - M.S.

That's not really what Ant is for.
Ant is primarily a build tool, and it's core functionalities revolve around that. Yes, it can be used for additional functions, but it's still best to use it what it was intended for. Finding a class inside a JAR file isn't what it's good at.
You may be better off just doing this in Java. Java offers functionality to open up JAR files and inspect the contents. You can use those to find the class you are looking for. Or, use another tool that's intended to do that, such as the Jarscan that Biju mentions.

I agree with rfeak this is not what ANT is designed for. Having said that, it can very be a frustrating to determine how to resolve missing class dependencies.....
I use the findjar website. It indexes most of the available open source libraries.

If you really need to do this, one approach that might work is to loop through all the JAR files and pass each one to the available task as the lone classpath path element. The class you're interested in would be used for the classname attribute.
Edit: Since it sounds like you're now entertaining non-Ant solutions, here's a variation of the find-my-class code:
import java.net.URL;
public class ClassFinder {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> c = Class.forName(args[0]);
URL url = c.getResource(c.getSimpleName() + ".class");
System.out.println("location of " + args[0] + ": " + url);
}
}
With Java 6, you can use classpath wildcards (see "Understanding class path wildcards"), so it should be easy to include your directory of JARs and see how fast it is.
Edit2: And if you want to find multiple locations...
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
public class ClassFinder {
public static void main(String[] args) throws IOException {
String classResourceName = args[0].replaceAll("\\.", "/") + ".class";
ClassLoader loader = ClassFinder.class.getClassLoader();
Enumeration<URL> classResources = (loader == null) ? ClassLoader.getSystemResources(classResourceName) : loader.getResources(classResourceName);
if (classResources.hasMoreElements()) {
System.out.println("Locations of " + args[0] + ":");
while (classResources.hasMoreElements()) {
URL url = classResources.nextElement();
URLConnection conn = url.openConnection();
String loc = (conn instanceof JarURLConnection) ? ((JarURLConnection)conn).getJarFile().getName() : url.toString();
System.out.println(loc);
}
} else {
System.out.println("No locations found for " + args[0]);
}
}
}

Related

How can I set up Soot when using it as a library?

I want to use Soot library to build an SSA from *.java file. But all the examples I found use Soot as standalone tool, not library. Can anyone give me example hot to do it in program?
For a start I am just trying to load my class from the source file and print it (TestClass.class is in the directory A/home/abdullin/workspace/test):
import soot.G
import soot.Scene
import soot.options.Options
fun main(args: Array<String>) {
G.reset();
Options.v().set_whole_program(true)
Scene.v().loadBasicClasses()
Scene.v().sootClassPath = "${Scene.v().defaultClassPath()}:/home/abdullin/workspace/test"
val sc = Scene.v().getSootClass("TestClass")
Scene.v().loadNecessaryClasses()
sc.setApplicationClass()
println(sc.name)
sc.methods.forEach {
println(it)
}
}
But when I run this, I get runtime exception Aborting: can't find classfile TestClass. If I change Scene.v().getSootClass("TestClass") to Scene.v().loadClassAndSupport("TestClass") as they do in some of their tutorials, soot finds my class, but it is not complete. It prints me signatures of class methods, but can't find their bodies, activeBody field is null.
TestClass
<TestClass: void <init>()>
<TestClass: void main(java.lang.String[])>
<TestClass: void f1()>
First, make sure that the Soot jar is in the classpath.
Then, set up Soot using the classes soot.G and soot.options.Options (G.reset() and Options.v().parse() are methods of interest, also see command line options).
Using soot.Scene.v().setSootClassPath() and similar you can tell Soot where to find the class files of the code you want to analyze.
You can then use Scene.v().getSootClass() to obtain SootClass objects. Make sure that Soot loads all classes after setting the class you want to analyze as main class:
mySootClass.setApplicationClass();
Scene.v().loadNecessaryClasses();
After this, you can use Soot to obtain various types of graphs and run you analyses, as described in the Survivor's guide
You can read this post (https://o2lab.github.io/710/p/a1.html). But if you try to analyze a jar file, you should unzip it and get a set of class files. Then you should add your classes directory into the soot_class_path.
Demo:
public static void main(String[] args) {
//spotbugs -- testing
String classesDir = "D:\\wkspace\\seed8\\dir\\spotbugs";
String mainClass = "edu.umd.cs.findbugs.LaunchAppropriateUI";
//set classpath
String jreDir = System.getProperty("java.home") + "\\lib\\jce.jar";
String jceDir = System.getProperty("java.home") + "\\lib\\rt.jar";
String path = jreDir + File.pathSeparator + jceDir + File.pathSeparator + classesDir;
Scene.v().setSootClassPath(path);
//add an intra-procedural analysis phase to Soot
TestCallGraphSootJar_3 analysis = new TestCallGraphSootJar_3();
PackManager.v().getPack("wjtp").add(new Transform("wjtp.TestSootCallGraph", analysis));
excludeJDKLibrary();
Options.v().set_process_dir(Arrays.asList(classesDir));
Options.v().set_whole_program(true);
//Options.v().set_app(true);
SootClass appClass = Scene.v().loadClassAndSupport(mainClass);
Scene.v().setMainClass(appClass);
Scene.v().loadNecessaryClasses();
//enableCHACallGraph();
enableSparkCallGraph();
PackManager.v().runPacks();
}
If you replace
SootClass appclass = Scene.v().loadClassAndSupport(mainclass);
Scene.v().setMainClass(appclass);
Scene.v().loadNecessaryClasses();
by
Scene.v().loadNecessaryClasses();
SootClass appclass = Scene.v().getSootClass(mainclass);
Scene.v().setMainClass(appclass);
, the program also works.

How to use Java Compile API to compile recursively? [duplicate]

I use the class javax.tools.JavaCompiler (jdk6) to compile a source file, but the source file depends on some jar file. How to set the classpath of the javax.tools.JavaCompiler?
The javax.tools.JavaCompiler#getTask() method takes an options parameter that allows to set compiler options. The following message describes an easy way to set them in order to access the calling program's classpath:
You need to configure the standard
java file manager to know about the
jar files(s) - you use the compiler
options argument to do that.
By default the java compiler object
only seems to know about the default
locations for bootclasspath, extdirs
and endorseddirs directories in terms
of its classpath.
You need to add the calling program's
current classpath to the java compiler
instance's which gets passed on the
the standard file manager, which will
then find classes in the jar files.
Here's how I do it in the compiler
wrapper I wrote
List<String> optionList = new ArrayList<String>();
// set compiler's classpath to be same as the runtime's
optionList.addAll(Arrays.asList("-classpath",System.getProperty("java.class.path")));
// any other options you want
optionList.addAll(Arrays.asList(options));
JavaCompiler.CompilationTask task = compiler.getTask(out,jfm,diagnostics,optionList,null,jfos);
All you'll need then is to get the proper classpath set when running the calling program.
The same problem occurred to me recently, finally I found two workarounds. You can set the class path either by invoke StandardJavaFileManager.setLocation(StandardLocation.CLASS_PATH, "YOUR_CLASS_PATH") or Compiler.getTask(ARG_0, ARG_1, ARG_2, CLASS_PATH_OPTIONS, just as the first answer posted here says.
I needed something simpler than the examples above.
The following is a self-contained example of using the built-in Java compiler, and setting the classpath for the compiler to use.
It is equivalent to creating a source file called HelloPrinter.java and then compiling it as follows:
javac -classpath C:\Users\dab\Testing\a.jar;c:\path\etc org\abc\another\HelloPrinter.java
Note how the classpath can be set using a String[] of options. This should be familiar if you're already used to running javac on the command line (as above).
This code is compatible with Java 6. You will need a JDK, not a JRE, for this to run. This example doesn't actually use the classpath. It all does is print "Hello". You can add an import statement to the generated source and call a method in an external Jar file to test this properly.
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class JavaCompilerExample {
public static void main(String[] args) throws Exception {
String className = "HelloPrinter";
String directoryName = "org/abc/another";
new File(directoryName).mkdirs();
FileOutputStream fos = new FileOutputStream(directoryName+"/"+className+".java");
PrintStream ps = new PrintStream(fos);
ps.println(
"package "+directoryName.replace("/", ".") + " ; "
+ "public class " +className +
"{ public static void main(String[] args){System.out.println(\"Hello\");} }");
ps.close();
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
String javacOpts[] = {"-classpath",
"C:\\Users\\dab\\Testing\\a.jar;c:\\path\\etc;",
directoryName+"/"+className + ".java"};
if ( javac.run(null, null, null, javacOpts)!=0 ) {
System.err.println("Error");
System.exit(1);
}
}
}

Query exist-db from Java

i want to query existdb from Java. i know there are samples but where can i get the necessary packages to run the examples?
in the samples :
import javax.xml.transform.OutputKeys;
import org.exist.storage.serializers.EXistOutputKeys;
import org.exist.xmldb.EXistResource;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.Database;
import org.xmldb.api.modules.XMLResource;
where can i get these ?
and what is the right standard connection string for exist-db? port number etc
and YES, i have tried to read the existdb documentation, but those are not really understandable for beginners. they are confusing.
All i want to do is write a Java class in eclipse that can connect to a exist-db and query an xml document.
Your question is badly written, and I think you are really not explaining what you are trying to do very well.
If you want the JAR files as dependencies directly for some project then you can download eXist and get them from there. Already covered several times here, which JAR files you need as dependencies is documented on the eXist website and links to that documentation have already been posted in this thread.
I wanted to add, that if you did want a series of simple Java examples that use Maven to resolve the dependencies (which takes away the hard work), then when we wrote the eXist book we provided just that in the Integration Chapter. It shows you how to use each of eXist's different APIs from Java for storing/querying/updating etc. You can find the code from that book chapter here: https://github.com/eXist-book/book-code/tree/master/chapters/integration. Included are the Maven project files to resolve all the dependencies and build and run the examples.
If the code is not enough for you, you might also want to consider purchasing the book and reading the Integration Chapter carefully, that should answer all of your questions.
i ended up with a maven project and imported some missing jars (like ws.commons etc) by manually installing them on maven.
the missing jars i copied from the existdb installation path on my local system.
then i got it to work.
from: http://exist-db.org/exist/apps/doc/devguide_xmldb.xml
There are several XML:DB examples provided in eXist's samples
directory . To start an example, use the start.jar jar file and pass
the name of the example class as the first parameter, for instance:
java -jar start.jar org.exist.examples.xmldb.Retrieve [- other
options]
Example: Retrieving a Document with XML:DB
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
import org.xmldb.api.*;
import javax.xml.transform.OutputKeys;
import org.exist.xmldb.EXistResource;
public class RetrieveExample {
private static String URI = "xmldb:exist://localhost:8080/exist/xmlrpc";
/**
* args[0] Should be the name of the collection to access
* args[1] Should be the name of the resource to read from the collection
*/
public static void main(String args[]) throws Exception {
final String driver = "org.exist.xmldb.DatabaseImpl";
// initialize database driver
Class cl = Class.forName(driver);
Database database = (Database) cl.newInstance();
database.setProperty("create-database", "true");
DatabaseManager.registerDatabase(database);
Collection col = null;
XMLResource res = null;
try {
// get the collection
col = DatabaseManager.getCollection(URI + args[0]);
col.setProperty(OutputKeys.INDENT, "no");
res = (XMLResource)col.getResource(args[1]);
if(res == null) {
System.out.println("document not found!");
} else {
System.out.println(res.getContent());
}
} finally {
//dont forget to clean up!
if(res != null) {
try { ((EXistResource)res).freeResources(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
if(col != null) {
try { col.close(); } catch(XMLDBException xe) {xe.printStackTrace();}
}
}
}
}
On the page http://exist-db.org/exist/apps/doc/deployment.xml#D2.2.6 a list of dependencies is included; unfortunately there is no link to this page on http://exist-db.org/exist/apps/doc/devguide_xmldb.xml (should be added);
The latest xmldb.jar documentation can be found on http://xmldb.exist-db.org/
All the jar files can be retrieved by installing eXist-db from the installer jar; the files are all in EXIST_HOME/lib/core
If you work with a maven project, try adding this to your pom.xml
<dependency>
<groupId>xmldb</groupId>
<artifactId>xmldb-api</artifactId>
<version>20021118</version>
</dependency>
Be aware that the release date is 2002.
Otherwise you can query exist-db via XML-RPC

Use Jsch to implement scp and additionally not reinvent the wheel

"How to copy a file using Jsch?" was the question first in place. As using Jsch is complicated and error-prone and also works very low-level, you need to program several lines to get a simple scp working.
So, how do I implement a scp (or even sftp) with as few lines of code as possible in Java and not violate the DRY principle?
You can use the libraries used by the Ant scp task:
package org.example.scp;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.optional.ssh.Scp;
public class ScpCopyExample {
public void downloadFile( String remoteFilePath, String localFilePath ) {
Scp scp = new Scp();
scp.setFile("username:password#host.example.org:" + remoteFilePath);
scp.setLocalTofile(localFilePath);
scp.setProject(new Project()); // prevent a NPE (Ant works with projects)
scp.setTrust(true); // workaround for not supplying known hosts file
scp.execute();
}
public static void main(String[] args) {
ScpCopyExample scpDemo = new ScpCopyExample();
scpDemo.downloadFile("~/test.txt", "testlocal.txt");
}
}
I did this with following jars in my classpath:
jsch-0.1.48.jar
ant-jsch-1.6.5.jar
ant-1.7.0.jar
ant-launcher-1.7.0.jar
This example can easily be extended to upload files or use SFTP instead.
Few lines as possible? Try this groovy example, which leverages the ANT scp task.
#Grapes([
#Grab(group='org.apache.ant', module='ant-jsch', version='1.8.4'),
#GrabConfig(systemClassLoader=true)
])
def ant = new AntBuilder()
ant.scp(file:"helloworld.doc", todir:"mark#remotehost:/home/mark/docs", password:"sEcReT")
The Grape annotations will download the jar dependencies at run-time.

How to get method signatures from a jar file?

I have a third-party jar file that comes with the javadocs for only part of the API. Is there a way to reverse engineer the jar file to obtain a complete listing of classes and methods?
jar tf will list the contents for you. javap will allow you to see more details of the classes (see the tools guide).
For instance if you have a class named mypkg.HelloWorld in a jar myjar.jar then run it like
javap -classpath myjar.jar mypkg.HelloWorld
However, are you sure you want to be using these unpublished APIs? It's usually a really bad idea.
As Scott said, you can use Eclipse to get a lot of what you're looking for.
I would recommend getting the JadClipse plugin which will decompile the .class files on the fly and show you actual Java code as you browse the classes in the IDE.
If you're using eclipse, you can just add it to a project's classpath and explore it using the treeview and/or content assist.
I'd assume other IDEs can do similar.
From a command-line point of view, you can unjar it (jar xf foo.jar) and use javap against all files.
Eclipse would work great
A Java Decompiler would translate the classes back into some semblence of source code that you could study to learn about the classes, the methods, their signatures, and maybe even some insight into valid values for some arguments (e.g. don't pass a null for this argument or you'll trigger a NullPointerException immediately). But roll up your sleeves to unjar the jar and run the decompiler against all the class files. This is essentially what Eclipse is doing for help text with undocumented classes.
Finally, of course, a "real programmer" would read the byte-code directly without need for a decompiler.
You can use the library WALA to read out all methods signatures. You'll however need to load Stub-Code for Java first. The following program should read out all the signatures:
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.types.ClassLoaderReference;
import java.util.jar.JarFile;
import java.io.IOException;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
public class methods {
public static void main(String[] args) throws IOException, ClassHierarchyException {
AnalysisScope scope = AnalysisScope.createJavaAnalysisScope();
scope.addToScope(ClassLoaderReference.Primordial, new JarFile("jSDG-stubs-jre1.5.jar"));
scope.addToScope(ClassLoaderReference.Application, new JarFile("myProgram.jar"));
IClassHierarchy cha = ClassHierarchy.make(scope);
for (IClass cl : cha) {
if (cl.getClassLoader().getReference().equals(ClassLoaderReference.Application)) {
for (IMethod m : cl.getAllMethods()) {
String ac = "";
if (m.isAbstract()) ac = ac + "abstract ";
if (m.isClinit()) ac = ac + "clinit ";
if (m.isFinal()) ac = ac + "final ";
if (m.isInit()) ac = ac + "init ";
if (m.isNative()) ac = ac + "native ";
if (m.isPrivate()) ac = ac + "private ";
if (m.isProtected()) ac = ac + "protected ";
if (m.isPublic()) ac = ac + "public ";
if (m.isSynchronized()) ac = ac + "synchronized ";
System.out.println(ac + m.getSignature());
}
}
}
}
}
If you use the adapted WALA-version from here it does Dalvik (e.g. Android Apps) as well.
a quick help for knowing methods of a normal class (not abstract class),I do the following .
new classname().press ctrl+space for methods listing in eclipse.
Use Eclipse > Package Explorer to see the classes and thier hierarchy.
Content Assist(autocomplete feature (ctrl + space)) is also a good help , but wouldnt recomend using an unpublished API

Categories