How to get the class variables count of a given.java file? - java

I need to create an application to get the class variables(attributes) count on a given .java file.So I developed a code using java reflection as below.So in here I create a new .java file with the same content of importing .java file in my src package because then that .java file can be accessible to the reflection purposes.But the problem is IDE is not figuring out the updates of that files automatically,which means even though the file is created already in my directory IDE doesn't figure it out instantly so I need to refresh the src package to notify the updates to the IDE.So how can I solve this issue.Therefor when you run this for first time there will be an exception of class not found exception ,because even though that .java file already there in the src folder IDE doesn't know.
I tried with eclipse, Intelij IDES.
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
importjava.util.concurrent.atomic.AtomicInteger;
public class AppInitializer {
public static void main(String args[])throws Exception{
AtomicInteger atomicInteger = new AtomicInteger();
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
try {
meth ();
} catch (ClassNotFoundException e) {
e.printStackTrace ( );
}
}
});
FileReader fr=new FileReader("C:\\Users\\User\\Desktop\\Sample.java");
int i;
StringBuffer str= new StringBuffer("");
while((i=fr.read())!=-1){
str.append ( (char)i );}
String s = String.valueOf ( str );
String replaceString=s.replaceAll ( "public class [^\\n]+", "public class filename{" );
System.out.println (replaceString );
fr.close();
try {
FileWriter myWriter = new FileWriter("src/filename.java");
myWriter.write( String.valueOf ( replaceString ) );
myWriter.close();
System.out.println("Successfully wrote to the file.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
static void meth() throws ClassNotFoundException {
Class classs= Class.forName ( "filename" );
int count = 0;
for (Field field : classs.getDeclaredFields ()){
count++;
}
System.out.println (count );
}
}

If you just add a new .java file to your program, that doesn't add a new class to it. You have to compile it at runtime in order for the Class.forName(...) method to be able to find it.
For a guide on how to do that, see this tutorial.

Related

How can I list all methods of all imported classes in a file using Java?

My objective is to look at some lines of codes of an external file and count the number of functions of a class are called then.
For example, if I have the following code:
import java.io.BufferedReader;
import whatever.MyClass;
import java.util.ArrayList;
...
...
public void example(){
InputStreamReader isr = new InputStreamReader (whatever);
MyClass object = new MyClass();
someArrayList.add(whatever2)
someArrayList.add(whatever3)
}
In this case, BufferedReader and MyClass functions were called once, and ArrayList functions were called twice.
My solution for that is get a list of all methods inside the used classes and try to match with some string of my code.
For classes created in my project, I can do the following:
jar -tf jarPath
which returns me the list of classes inside a JAR . And doing:
javap -cp jarPath className
I can get a list of all methods inside a JAR whit a specific class name. However, what can I do to get a external methods names, like add(...) of an "external" class java.util.ArrayList?
I can't access the .jar file of java.util.ArrayList correct? Anyone have another suggestion to reach the objective?
The compiler doesn't put the imports into the object file. It throws them away. Import is just a shorthand to the compiler.(Imports are a compile-time feature ).
first step :
use Qdox https://github.com/paul-hammant/qdox to get all the imports in a class :
String fileFullPath = "Your\\java\\ file \\full\\path";
JavaDocBuilder builder = new JavaDocBuilder();
builder.addSource(new FileReader( fileFullPath ));
JavaSource src = builder.getSources()[0];
String[] imports = src.getImports();
for ( String imp : imports )
{
System.out.println(imp);
}
second step :
inspire from that code , loop through your imports (String array) and apply the same code and you will get the methods .
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Tes {
public static void main(String[] args) {
Class c;
try {
c = Class.forName("java.util.ArrayList");
Arrays.stream(getAccessibleMethods(c)).
forEach(System.out::println);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Method[] getAccessibleMethods(Class clazz) {
List<Method> result = new ArrayList<Method>();
while (clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
result.add(method);
}
clazz = clazz.getSuperclass();
}
return result.toArray(new Method[result.size()]);
}
}
Output :
public void java.util.ArrayList.add(int,java.lang.Object)
public boolean java.util.ArrayList.add(java.lang.Object)
public boolean java.util.ArrayList.remove(java.lang.Object)
public java.lang.Object java.util.ArrayList.remove(int)
public java.lang.Object java.util.ArrayList.get(int)
public java.lang.Object java.util.ArrayList.clone()
public int java.util.ArrayList.indexOf(java.lang.Object)
public void java.util.ArrayList.clear()
.
.
.
All the code - one class :
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.model.JavaSource;
public class Tester {
public static void main(String[] args) {
// put your .java file path
// CyclicB is a class within another project in my pc
String fileFullPath =
"C:\\Users\\OUSSEMA\\Desktop\\dev\\OCP_Preparation\\src\\w\\CyclicB.java";
JavaDocBuilder builder = new JavaDocBuilder();
try {
builder.addSource(new FileReader( fileFullPath ));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JavaSource src = builder.getSources()[0];
String[] imports = src.getImports();
for ( String imp : imports )
{
Class c;
try {
c = Class.forName(imp);
Arrays.stream(getAccessibleMethods(c)).
forEach(System.out::println);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public static Method[] getAccessibleMethods(Class clazz) {
List<Method> result = new ArrayList<Method>();
while (clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
result.add(method);
}
clazz = clazz.getSuperclass();
}
return result.toArray(new Method[result.size()]);
}
}
Output all the methods within the classes imported in the file CyclicB.java :
private void java.lang.Throwable.printStackTrace(java.lang.Throwable$PrintStreamOrWriter)
public void java.lang.Throwable.printStackTrace(java.io.PrintStream)
public void java.lang.Throwable.printStackTrace()
public void java.lang.Throwable.printStackTrace(java.io.PrintWriter)
public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
.
.
.
You may look into OpenJDK project that has a Java compiler. Learn to build the modified versions. Investigate the syntax analysis layer of this compiler and find where the method calls are handled. Put the logging into these locations and now you only need to build your java file with the modified compiler to get the information about the calls.
The build is complex, but you will likely only need a careful editing in a few files. It is not exactly very low hanging fruit but I think it should be possible to discover these files and make changes in them, and still may be a simpler/cleaner approach than to implement the own Java syntax parser (also doable with JavaCC).
If you also need to track calls from the external libraries, build them with the modified compiler as well and you will have the needed records.
GNU Classpath is another open source project where you can do the similar thing, and it may be easier to build. However, unlike OpenJDK, GNU Classpath java system library is not complete.
This approach may not discover some methods called during reflection. But it would discover that reflection framework methods have been called. If it is a security - related project, the simplest would be to agree that reflection is not allowed. It is uncommon to use reflection in a normal Java application that is not a framework.

Reading multiple files in directory and printing specific content

What I am trying to achieve is basically a Java file which looks through a specific directory on the users computer, search all the files in the directory for specific word (in this case an email) and then at the end print them out.
The current script of which I have now, looks for all the files in a certain directory, prints out those file names. As well as that I have also figured out how to have that script search through one file for a specific word and then print it out. The only problem is that although it searches through that one file and gets that word/phrase it has to be given the full directory and file to work. I just want it to have a specific directory and then search all the files in it. I have tried doing this using the directory variable of which I have created to find all files, but it does not work when using that as the directory for the files to search through to find the word(s).
Here underneath is the part of my code which is used for the function I want. The actual function is called in my real script so don't worry about that as it is working. I have also just commented in the script what variable I want to work where.
package aProject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class aScanner {
static String usernameMac = System.getProperty("user.name");
final static File foldersMac = new File("/Users/" + usernameMac + "/Library/Mail/V2"); // this is the right directory I want to look through
public static void listFilesForFolder(final File foldersMac) {
for (final File fileEntry : foldersMac.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
try {
BufferedReader bReaderM = new BufferedReader(new FileReader("/Users/username/Library/Mail/V2/AosIMAP-/INBOX.mbox/longnumber-folder/Data/Messages/1.emlx")); //this is where I would like the foldersMac variable to work in, instead of this full directory
String lineMe;
while((lineMe = bReaderM.readLine()) != null)
{
if(lineMe.contains(".com"))
System.out.println(lineMe);
}
bReaderM.close();
}
catch (IOException e) {
}
} else {
System.out.println(fileEntry.getName());
}
}
}
}
I think this is what you're trying to achieve:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class aScanner {
static String usernameMac = System.getProperty("user.name");
final static File foldersMac = new File("/Users/" + usernameMac + "/Library/Mail/V2");
public static void main(String[] args) throws IOException {
listFilesForFolder(foldersMac);
}
public static void listFilesForFolder(final File foldersMac) throws IOException {
for (final File fileEntry : foldersMac.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
} else {
ArrayList<String> lines = new ArrayList<>();
try (BufferedReader bReaderM = new BufferedReader(new FileReader(fileEntry))) {
String lineMe;
while ((lineMe = bReaderM.readLine()) != null) {
if (lineMe.contains(".com")) {
lines.add(lineMe);
}
}
}
if (!lines.isEmpty()) {
System.out.println(fileEntry.getAbsolutePath() + ":");
for (String line : lines) {
System.out.println(" " + line.trim());
}
}
}
}
}
}
I think your problem lies around your recursion logic,
You go down recursively in the directory structure, you walk through you tree, but write out nothing cause of this if statement:
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
...
}
Close that If statement earlier, then it should work.

Further analysis of Java source using Java (and reflection)

I try to analyze Java source code in Java6. ANTLR4 does great job in lexical analysis indeed but now I wonder if more advanced problems, such as listing inherited methods, can be managed.
My idea (according to some googling):
load source files
get system compiler by ToolProvider.getSystemJavaCompiler() and compile sources via run() into .class files
[maybe?] pack .class files to .jar and load them somehow
use Java reflection to analyze compiled classes
delete .class files
write output (e.g. inherited methods/fields etc.)
Bullets 1, 4, 5 and 6 are clean enough and well described. I belive nr. 2 can be solved using this tutorial. So my core problem is nr. 3 as I can't figure out how to load .class files and analyse them.
Any ideas? Is this even possible? If so, how? Could you recommend me either a tutorial or examples? Is my idea even correct?
I prefer not using third-party libraries as I'd like to understand in depth.
Thanks to all comments and google I finally figured it out - basically I needed an example like this:
/* Usage
--------
$ javac CompileJarLoadReflect.java
$ java CompileJarLoadReflect MyClass YourClass CompileJarLoadReflect
MyClass.java compilation is successful
YourClass.java compilation is successful
CompileJarLoadReflect.java compilation is successful
3 files successfully compiled
Class MyClass
myMethod
Class YourClass
yourMethod
Class CompileJarLoadReflect
main
compile
compile
load
jar
*/
/* Thanks to
------------
http://www.java2s.com/Code/Java/File-Input-Output/CreateJarfile.htm
http://stackoverflow.com/questions/194698/how-to-load-a-jar-file-at-runtime/673414#673414
*/
import javax.tools.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Method;
/** Simple compilation, packaging and loading example */
public class CompileJarLoadReflect {
/** JAR buffer size*/
public static int BUFFER_SIZE = 10 * 1024;
/** Compile all files given (by their location) */
public void compile(String[] files) throws Exception {
for (String f : files) compile(f + ".java");
System.out.println(files.length + " files successfully compiled");
}
/** Compile one particular file */
protected void compile(String f) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, f);
if (compilationResult == 0) System.out.println(f + " compilation is successful");
else throw new Exception("Compilation error at file " + f);
}
/** Pack tobeJared classes into jarName */
public void jar(String jarName, String[] tobeJared) throws Exception {
File archiveFile = new File(jarName);
byte buffer[] = new byte[BUFFER_SIZE];
FileOutputStream stream = new FileOutputStream(archiveFile);
JarOutputStream out = new JarOutputStream(stream, new Manifest());
for (String name : tobeJared) {
File f = new File(name + ".class");
if (f == null || !f.exists() || f.isDirectory()) throw new Exception("Jar problem at file " + name);
JarEntry jarAdd = new JarEntry(f.getName());
jarAdd.setTime(f.lastModified());
out.putNextEntry(jarAdd);
FileInputStream in = new FileInputStream(f);
while (true) {
int nRead = in.read(buffer, 0, buffer.length);
if (nRead <= 0) break;
out.write(buffer, 0, nRead);
}
in.close();
}
out.close();
stream.close();
}
/** Load jar archive at jarName and then print methods of all classes in clazzes */
public void load(String jarName, String[] clazzes) throws Exception {
File file = new File(jarName);
URL url = file.toURL();
URL[] urls = new URL[]{url};
ClassLoader cl = new URLClassLoader(urls);
for (String c : clazzes) {
System.out.println("Class " + c);
Class cls = cl.loadClass(c);
Method[] methods = cls.getDeclaredMethods();
for (Method m : methods) System.out.println("\t" + m.getName());
}
}
/** Try everyting out, use params without .java */
public static void main(String[] args) {
String jarName = "output.jar";
try {
CompileJarLoadReflect cjlr = new CompileJarLoadReflect();
cjlr.compile(args);
cjlr.jar(jarName, args);
cjlr.load(jarName, args);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
I hope it helps others.

Reading Text Files Java:15 Error: Cannot Find Symbol

Im trying to read the content from a text file. ReadTextFile.java and ReadTextFileTest.java are in the same package ReadTextFile. I am using 2 packages in one project, ReadTextFiles and CreateTextfiles. ReadTextFiles package reads content from a text file and CreateTextFile package inputs content into a text file.
When I get to the command prompt I try to compile the java file into a class file by javac ReadTextFileTest.java. I get the following error everytime.
ReadTextFileTest.java:15 error: cannot find symbol
ReadTextFile application = new ReadTextFile();
^
symbol: class ReadTextFile
location: class ReadTextFileTest
ReadTextFileTest.java:15 error: cannot find symbol
ReadTextFile application = new ReadTextFile();
^
symbol: class ReadTextFile
location: class ReadTextFileTest
11.2 errors
Im guessing its having trouble recognizing the object I created of the ReadTextFile.java class.
Here is the two classes I used:
ReadTextFile.java
package ReadTextFile;
import java.io.File;
import java.io.FileNotFoundException;
import java.lang.IllegalStateException;
import java.util.NoSuchElementException;
import java.util.Scanner;
import AccountRecord.AccountRecord;
public class ReadTextFile
{
private Scanner input;
public void openFile()
{
try
{
input = new Scanner( new File( "clients.txt" ) );
}
catch ( FileNotFoundException fileNotFoundException )
{
System.err.println( "Error opening file." );
System.exit(1);
}
}
public void readRecords()
{
AccountRecord record = new AccountRecord();
System.out.printf( "%-10s%-12s%-12s%10s\n", "Account",
"First Name", "Last Name", "Balance" );
try
{
while ( input.hasNext() )
{
record.setAccount( input.nextInt() );
record.setFirstName( input.next() );
record.setLastName( input.next() );
record.setBalance( input.nextDouble() );
System.out.printf( "%-10d%-12s%-12s%10.2f\n",
record.getAccount(), record.getFirstName(),
record.getLastName(), record.getBalance() );
}
}
catch ( NoSuchElementException elementException )
{
System.err.println( "File improperly formed." );
input.close();
System.exit( 1 );
}
catch ( IlegalStateException stateException )
{
System.err.println( "Error opening file." );
System.exit( 1 );
}
}
public void closeFile()
{
if ( input !=null )
input.close();
}
}
ReadTextFileTest.java
package ReadTextFile;
public class ReadTextFileTest
{
public static void main(String[] args)
{
ReadTextFile application = new ReadTextFile();
application.openFile();
application.readRecords();
application.closeFile();
}
}
Add import statement as below:-
package ReadTextFile;
import ReadTextFile;
public class ReadTextFileTest
{
public static void main(String[] args)
{
ReadTextFile application = new ReadTextFile();
application.openFile();
application.readRecords();
application.closeFile();
}
}
Remove
package ReadTextFile;
ReadTextFile is not a package but a class. Remove this line and try to compile again.
You must have meant
import readTextFile;
but if you make sure it is in the same directory, you don't have to import it. So, just delete the first line of ReadTextFileTest.
Edit after comment:
Generally, avoid naming packages with the same names as classes ( although as #Masud said in the comments it is possible). You should follow these naming conventions.

unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown [duplicate]

This question already has an answer here:
What does "error: unreported exception <XXX>; must be caught or declared to be thrown" mean and how do I fix it?
(1 answer)
Closed 8 months ago.
I am creating a class -- just a class, no main() and I am receiving the error of "unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown" at this line:
FileOutputStream outStr = new FileOutputStream(FILE, true);
I don't understand; I put in a try{} catch{} block and it's still reporting the error.
Additionally, it's also reporting an "illegal start of type" for the try and both catch lines, and it's also saying that ';' is expected for both catch lines.
I'm using the NetBean IDE, FYI.
Thank you for any help.
Here is the full code:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.FileNotFoundException;
public class UseLoggingOutputStream
{
String FILE = "c:\\system.txt";
try
{
FileOutputStream outStr = new FileOutputStream(FILE, true);
}
catch(FileNotFoundException fnfe)
{
System.out.println(fnfe.getMessage());
}
catch(IOException ioe)
{
System.out.println(ioe.getMessage());
}
}
You need to put the file processing statements inside a method:
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
public class UseLoggingOutputStream {
public void myMethod() {
String file = "c:\\system.txt";
try {
FileOutputStream outStr = new FileOutputStream(file, true);
} catch(FileNotFoundException fnfe) {
System.out.println(fnfe.getMessage());
}
}
}
All functional code needs to go into methods - I don't see a method in your code - that's the illegal start of type problem. The other compile errors should become clearer once you get the basics down.
public class Foo {
public void doSomething() {
//code here
}
}
Move this code to some method or at least to a static initializer block.
import java.io.*;
import java.util.*;
public class SortNames {
private String[] strings = new String[10];
private int counter;
public SortNames() {
ArrayList<String> names = new ArrayList<String>();
Scanner scan = null;
File f = null;
try{
f = new File("names.txt");
scan = new Scanner(f);
while(scan.hasNext()) names.add(scan.next());
}
finally{scan.close();}
Collections.sort(names);
for(String s:names) System.out.println(s);
}
}
Sorry if this isn't helpful to you, but I was able to solve this exact issue by adding " throws FileNotFoundException " to my method call that contained the FileWriter. I know this may not be helpful since you aren't using methods, but then again, maybe it is.

Categories

Resources