I am trying to run reflection to check if some android class exists in Java ( such as Toast ). I am running it from my Command line using this code:
String [] packages = new String[] {"java.lang.",
"android.widget.",
"android.util.",
"android.app.",
"android.view.",
"android.content."};
for (int i = 0; i < packages.length; i++){
String package_name = packages[i];
try {
Class<?> clazz = Class.forName(package_name + "Toast");
System.out.println("class Exists");
return clazz;
}
catch (ClassNotFoundException e){
System.out.println("class " + package_name + "Toast doesnt exists");
}
}
However, I get the output:
class android.widget.Toast doesn't exists ( but I know it does this is where the class is at)
any ideas?
EDIT : I am trying to write a Java class that is not running from Android Studios, but compiles and runs using javac from cmd line.
Because you are executing this on the command line there is no reason the Android packages/classes should be available to the runtime unless it is explicitly included. The output of your program makes sense - unless you provide the correct Android libraries to the program then there is not going to be a match when you try to resolve a particular Android class such as Toast.
The answer is essentially using Java's classpath effectively. By default, without stating an argument, it is the working directory '.'.
Add to it using -classpath as an argument. Compile naively:
javac YourReflectionTest.java
as you know the program finds no matches.
If you do this javac will also succeed
javac -classpath ".;/opt/android-sdk/platforms/android-21/android.jar" YourReflectionTest.java
If you run the program, and try
java YourReflectionTest
It will still produce the same result. Why? At run-time, there are still no Android classes loaded. You are by default only going to get the java system libraries included in your installation of JDK.
But, if you provide an appropriate path at runtime, then suddenly all the magic happens:
java -classpath ".;/opt/android-sdk/platforms/android-21/android.jar" YourReflectionTest
Note, Android API level 21 is just an example here and any could be used depending on which features you're trying to test.
When I execute your code, I get get this output:
class java.lang.Toast doesnt exists
class Exists
Since you iterate over all packages, you get an output for every package, no matter if your class exists or not, and you only stop when you find a match.
I think what you are trying to achieve is to always get only 1 output: either the class exists, or it doesn't. You could do that by creating a method classExists() and then using the java stream API to find if any of your packages contains your class Toast:
public void myMethod() {
List<String> packages = Arrays.asList(
"java.lang.",
"android.widget.",
"android.util.",
"android.app.",
"android.view.",
"android.content."
);
String className = "Toast";
if (packages.stream().anyMatch(pkg -> classExists(pkg + className))) {
System.out.println("class exists");
} else {
System.out.println("class doesnt exist");
}
}
boolean classExists(String fullClassName) {
try {
Class.forName(fullClassName);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
A simple method using reflection to check if a class exists or not:
private boolean doesClassExist(String name) {
try {
Class c = Class.forName(name);
if (c != null) {
return true;
}
} catch (ClassNotFoundException e) {
// Class not found
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
Use Case:
boolean classExists = doesClassExist("android.widget.Toast");
Related
This question already has an answer here:
File not found java
(1 answer)
Closed 2 years ago.
I have a java project in eclipse and have a method that reads information from a file. When I do a JUnit test on the method, it is unable to find the file even though it is in my working tree and I used the correct class path declaration.
Method to read file:
public static ArrayList<Issue> readIssuesFromFile(String filename) {
ArrayList<Issue> issues = new ArrayList<Issue>();
try {
Scanner sc = new Scanner(new FileInputStream(filename));
String text = "";
while(sc.hasNextLine()) {
text+= sc.nextLine();
text+= "\n";
}
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage());
}
}
JUnit Test:
public void testReadIssueFromFile() {
String test = "test-files/valid_file.txt";
try {
ArrayList<Issue> issues = IssueReader.readIssuesFromFile(testFile);
assertEquals(issues.get(0).getIssueId(), 0);
} catch (Exception e) {
fail(e.getMessage());
}
}
Working Tree:
->Project
->src
->.java file containing method
->test
->JUnit test file
->test-files
->txt file
According to your working tree i think your path should be:
../test-files/valid_file.txt
The path you used (test-files/valid_file.txt) means search in the folder of your JUnit file a folder named test-files and search inside this folder a file named valid_file.txt.
According to your working tree it's not the case. So you need .. to move to the above level where you can find the folder test-files.
If it still doesn't work, maybe try to debug you program by printing the paths that you have used like this:
try {
/* Here you can replace the period with another path like "test-files/valid_file.txt"
* to see the absolute path of it
*/
System.out.print(new java.io.File( "." ).getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
I'm working on a text editor project right now for my programing class and I'm getting an error I've never seen before when I try to run it. It's a fairly long explanation, but basically, i'm Using an editor class that uses several other classes to create a linked list, store a text file in it, and then allow modification of the file. I'm supposed to run it in a linux environment, and the file in question is supposed to be entered as a 'command-line' argument. However, every time I try running it, I get the following error
Exception in thread "main" java.lang.NoClassDefFoundError: myEditor
Caused by: java.lang.ClassNotFoundException: myEditor
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
Could not find the main class: myEditor. Program will exit.
As for the program itself:
import java.util.Scanner;
import java.util.Iterator;
import java.io.*;
public class myEditor {
public static void saveToFile(String text, String filename) throws IOException{
PrintWriter out = new PrintWriter(new File(filename));
out.println(text);
out.close();
}
public static void main(String args[]) {
boolean quit = false;
try {
if(args.length!=1) {
throw new IllegalArgumentException();
}
String filename = args[0];
Scanner input = new Scanner(new File(filename));
//Add exception
UnorderedList<String> list = new UnorderedList<String>();
while(input.hasNextLine()) {
if(list.head==null) {
list.addToFront(input.nextLine());
}
list.addToRear(input.nextLine());
}
System.out.println(">");
do {
Scanner command = new Scanner(System.in);
String comm = command.next();
String[] comm1 = comm.split(" ");
if(comm1[0].equalsIgnoreCase("I")&&comm1[1].equals("")) {
System.out.println("Type a line of text >");
comm = command.next();
list.addToRear(comm);
}
else if(comm1[0].equalsIgnoreCase("I")&&!comm1[1].equals("")) {
int linNum = Integer.parseInt(comm1[1]);
Iterator<String> itr = list.iterator();
String current = "";
for(int count=0;count<linNum;count++) {
current = itr.next();
}
list.addAfter(comm, current);
}
else if(comm1[0].equalsIgnoreCase("D")&&!comm1[1].equals("")) {
int linNum = Integer.parseInt(comm1[1]);
if(linNum<=list.count&&linNum>0) {
Iterator<String> itr = list.iterator();
String current = "";
for(int count=0;count<linNum;count++) {
current = itr.next();
}
list.remove(current);
}
}
else if(comm1[0].equalsIgnoreCase("L")) {
list.toString();
}
else if(comm1[0].equalsIgnoreCase("E")&&!comm1[1].equals("")) {
saveToFile(list.toString(), filename);
quit = true;
break;
}
}
while(!quit);
}
catch(IllegalArgumentException e) {
System.err.print(e.getMessage());
}
catch(FileNotFoundException e) {
System.err.print(e.getMessage());
}
catch(IOException e) {
System.err.print(e.getMessage());
}
}
}
Obviously, there's a load of other classes I used with this one, but it seems to me the error doesn't lie in them. Does anyone have any experience with this kind of error?
EDIT: I almost forgot to mention, by command line argument, I meant that the file this is supposed to be worked with should already be in the linux directory it was placed it. It should apparently take up args[0]
java.lang.classNotFoundException comes in following cases:
1) When we try to load a class by using Class.forName() method and .class file or binary of class is not available in classpath.
2) When Classloader try to load a class by using findSystemClass () method.
3) While using loadClass() method of class ClassLoader in Java.
So it is clear that jvm not able to find your class. Now question is who will tell the jvm that where to look for a class? answer is -- CLASSPATH environment variable.
because Classpath is a parameter—set either on the command-line, or through an environment variable—that tells the Java Virtual Machine or the Java compiler where to look for user-defined classes and packages.
So you can set the CLASSPATH at run time "java $CLASSPATH:. myEditor" or at environment as always to look for your current directory and it will fix the problem.
On linux variant you can set this at .bashrc file ( if using bash) , can use set command, can set at .bash_profile. On Windows you will find the same at "System-->Properties"
Make sure you have compiled your class by javac
Please execute the command with classpath such as
java $CLASSPATH:. myEditor
The error is saying that it can't find the class myEditor at runtime however was present at compile time. In my tests, when I ran the class and I was missing something it would give me that exact error. Are all your classes in the same place (Or properly organized)? Try looking over all the .class files that you need and make sure they are all there. If you provide some more details of how you're compiling and running this I can edit this answer to give you a better one!
I seem to be having what I believe is a ClassLoader problem using db4o with NetBeans. When I run the exact same code from the terminal with the same jar files from .../jre/lib/ext, everything works fine. The issue is that when I make a native query on some Classes that are loaded at runtime using a ClassLoader, I get an empty List from the database where I should definitely be getting a List with some elements (as I said, the same code works fine from the command line). I feel like this may be because the NetBeans ClassLoader works differently than the JVM ClassLoader, but I don't know, I'm certainly no expert on either. Here is the code from my main function.....
////////////////////////////////////////////////////////////////////////////////////////////
package gql;
import java.io.*;
import java.util.*;
import com.db4o.*;
public class GQL {
////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
////////////////////////////////////////////////////////////////////////////
private static ObjectSet dbObjects;
private static LinkedList classes = new LinkedList();
private static String dbPath, classPath;
private static ObjectContainer db;
private static ClassLoader coreClassLoader =
ClassLoader.getSystemClassLoader();
private static ClassLoader subClassLoader =
ClassLoader.getSystemClassLoader();
public static void main(String[] args) {
////////////////////////////////////////////////////////////////////////
// CREATE DATABASE OBJECT
////////////////////////////////////////////////////////////////////////
// If no path to a database is provided on the command line, print
// error and exit program
if (args.length < 1) {
System.err.println("\nError: no database path provided.\n");
return;
} else if (args.length > 1) {
dbPath = args[0];
// TODO - dubug command line classpath
classPath = args[1];
db = Db4o.openFile(dbPath);
} else { // We assume that the database Classes are stored somewhere
dbPath = args[0]; // along the CLASSPATH, and therefore classPath
classPath = ""; // can be left empty
db = Db4o.openFile(dbPath);
}
System.out.print("GQL> ");
// The prompt of the interpreter is within a do-while loop, which can
// be terminated by entering "exit"
do {
try {
/////////////////////////////////////////////////////////////////
// READ IN QUERY FILE
/////////////////////////////////////////////////////////////////
// We create a Scanner object to read tokens from the standard in
// stream - these will be our DLOG files provided by the user
Scanner fileScanner = new Scanner(System.in);
String GQLFile = fileScanner.next();
// Break loop and exit program if user enters "exit"
if (GQLFile.equalsIgnoreCase("exit")) {
break;
// If the user input is not preceeded by "#" and teminated with
// ";" then the input is invalid - the user is prompted again
} else if (!(GQLFile.substring(0,1).equals("#")) ||
!(GQLFile.substring(GQLFile.length()-1,
GQLFile.length()).equals(";"))) {
System.out.println("\nInvalid input.\nUsage: "
+ " #filename;\n");
System.out.print("GQL> ");
continue;
} else {
// Parse out the "#" and ";" from the user's input and send
// this to a file Reader object
GQLFile = GQLFile.substring(1,GQLFile.length()-1);
}
// Now we create a reader object and give it the user's parsed
// input - in the event of a FileNotFoundException, the user is
// prompted again
Reader reader;
try {
reader = new FileReader(GQLFile);
} catch (FileNotFoundException e) {
System.out.println("\nFile " + GQLFile +
" does not exist.\n");
System.out.print("GQL> ");
continue;
}
/////////////////////////////////////////////////////////////////
// PARSE QUERY
/////////////////////////////////////////////////////////////////
// The parser and Lexer objects are created in the parser.java
// and Lexer.java files, respectively - The parser takes the
// Lexer as an argument - the value variable generated by the
// parse() method will return the topmost grammar construct,
// which in this case is a Query object
parser p = new parser(new Lexer(reader));
Query query = (Query) p.parse().value;
/////////////////////////////////////////////////////////////////
System.out.println("\n----------------------------Input Query-----" +
"-----------------------\n");
System.out.println("\n SUCCESSFUL PARSE " +
" \n");
System.out.println("--------------------------------------" +
"------------------------------\n");
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// LOAD ALL CLASSES USED IN DATABASE INTO RUNTIME
/////////////////////////////////////////////////////////////////
// databse Classes should be kept on the CLASSPATH, or the path
// to these classes should be provided as a second command line
// argument
boolean coreClassesLoaded = loadCoreClasses(coreClassLoader,
classPath);
if (!coreClassesLoaded) {
System.err.println("\nError: one or more of core Classes"
+ "Node, Egge and SimplePath could not be found.\n");
db.close();
return;
}
//
System.out.println("Core classes loaded.\n");
boolean subclassesLoaded = query.loadSubclasses(subClassLoader,
classPath);
if (!subclassesLoaded) {
System.err.println("\nError: subclasses could not be" +
" loaded.\n");
db.close();
return;
}
//
System.out.println("Subclasses loaded.\n");
/////////////////////////////////////////////////////////////////
// MAKE SURE THE DATABASE ACTUALLY CONTAINS SOME OBJECTS AND,
// IF SO, PUT AN INSTANCE OF EACH CLASS REPRESENTED INTO THE
// LINKEDLIST CLASSLIST - SINCE WE LOADED THE DATABASE CLASSES
// INTO THE RUNTIME ENVIRONMENT, OBJECTS RETURNED BY DATABASE
// QUERIES WILL REMAIN TRUE TO THEIR TYPE; IF WE HADN'T DONE
// THIS, THESE OBJECTS WOULD BE RETURNED AS TYPE GENERICOBJECT
/////////////////////////////////////////////////////////////////
dbObjects = db.queryByExample(Object.class);
if (dbObjects.hasNext()) {
query.addClassesToList(dbObjects, classes);
} else {
System.err.println("\nError: no objects in database.\n");
db.close();
return;
}
//
System.out.println(classes);
/////////////////////////////////////////////////////////////////
// SEMANTIC CHECKS //
/////////////////////////////////////////////////////////////////
boolean headArgsAreSet = query.setHeadArgClasses(classes);
if (!headArgsAreSet) {
db.close();
return;
}
boolean typesMatch = query.checkQueryTypes(db);
if (!typesMatch) {
db.close();
return;
}
/////////////////////////////////////////////////////////////////
// EVALUATION
/////////////////////////////////////////////////////////////////
query.evaluateQuery(db);
} catch (Exception e) {
System.out.println("\nSYNTAX ERROR\n");
e.printStackTrace();
}
System.out.print("GQL> ");
} while (true);
System.out.println("\nExiting...\n");
db.close();
}
private static boolean loadCoreClasses(ClassLoader coreClassLoader,
String classPath) {
try {
coreClassLoader.loadClass("Node");
coreClassLoader.loadClass("Edge");
coreClassLoader.loadClass("SimplePath");
} catch (ClassNotFoundException cnfe) {
return false;
}
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////////////
The strange thing is, the classes I need are definitely getting loaded into the runtime environment, as I use them to set some Class member variables, for example in the "SEMANTIC CHECKS" section. So it's like the application can see the dynamically loaded Classes, but the db4o API/database cannot. Also, I have the Class jar and the db4o jar set up as Netbeans libraries, not just in .../jre/lib/ext. Here's a snippet of the code in the Class where I actually use the db4o native query that's giving me problems...
////////////////////////////////////////////////////////////////////////////////////////////
public void evaluateQuery(ObjectContainer db) {
if (this.hasPredicate) {
;
} else {
if (this.isNode) {
List nodes = db.query(new Predicate() {
#Override
public boolean match(Node node) {
return (node.getName().equals("5"));
}
});
System.out.println("\n_________________RESULT__________________________");
System.out.println("\nNode: " + nodes.get(0).getName()
//+ ".\n");
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
... if I do the following instead I still get an empty List...
////////////////////////////////////////////////////////////////////////////////////////////
public void evaluateQuery(ObjectContainer db) {
if (this.hasPredicate) {
;
} else {
if (this.isNode) {
List nodes = db.queryByExample(Node.class);
System.out.println(nodes.size());
for (int i = 0; i < nodes.size(); i++) {
System.out.println("\nNode: " + nodes.get(i).getName());
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
Hmm, I don't see any dynamic class loading problems here. You're using the system's classloader, which should be visible to db4o. You don't even need to load the classes, db4o will do that with the classloaders.
Are you sure that the application picks up the same database? Are you using a relative path?
Btw you can explicitly set the classloader for db4o, like this.
EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
JdkLoader classLookUp = new ClassLoaderLookup(
Thread.currentThread().getContextClassLoader(),
new URLClassLoader(new URL[]{new URL("file://./some/other/location")}));
configuration.common().reflectWith(new JdkReflector(classLookUp));
ObjectContainer container = Db4oEmbedded.openFile(configuration,"database.db4o");
Well it seems like this is a bug in Linux/Netbeans for Linux/Db4o. I used the exact same source files on a windows box and everything worked fine. I'm pretty disappointed, I don't want to have to use windows for this project. :/
i want to create a hardlink from a file "C:\xxx.log" to "C:\mklink\xxx.log" .
In cmd it works of course, but i want to write a software for this usecase.
So have to locate the existing file
Then make a hardlink
Then delete the old file
I started to implement but, i just know how to create a file. On google i found nothing about mklink \H for Java.
public void createFile() {
boolean flag = false;
// create File object
File stockFile = new File("c://mklink/test.txt");
try {
flag = stockFile.createNewFile();
} catch (IOException ioe) {
System.out.println("Error while Creating File in Java" + ioe);
}
System.out.println("stock file" + stockFile.getPath() + " created ");
}
There are 3 ways to create a hard link in JAVA.
JAVA 1.7 Supports hardlinks.
http://docs.oracle.com/javase/tutorial/essential/io/links.html#hardLink
JNA, The JNA allows you to make native system calls.
https://github.com/twall/jna
JNI, you could use C++ to create a hardlink and then call it through JAVA.
Hope this helps.
Link (soft or hard) is a OS feature that is not exposed to standard java API. I'd suggest you to run command mklink /h from java using Runitme.exec() or ProcessBuilder.
Or alternatively try to find 3rd party API that wraps this. Also check what's new in Java 7. Unfortunately I am not familiar with it but I know that they added rich file system API.
For posterity, I use the following method to create links on *nix/OSX or Windows. On windows mklink /j creates a "junction" which seems to be similar to a symlink.
protected void makeLink(File existingFile, File linkFile) throws IOException {
Process process;
String unixLnPath = "/bin/ln";
if (new File(unixLnPath).canExecute()) {
process =
Runtime.getRuntime().exec(
new String[] { unixLnPath, "-s", existingFile.getPath(), linkFile.getPath() });
} else {
process =
Runtime.getRuntime().exec(
new String[] { "cmd", "/c", "mklink", "/j", linkFile.getPath(), existingFile.getPath() });
}
int errorCode;
try {
errorCode = process.waitFor();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Link operation was interrupted", e);
}
if (errorCode != 0) {
logAndThrow("Could not create symlink from " + linkFile + " to " + existingFile, null);
}
}
I am trying to write a file on a C:\ drive, but I get an exception.
java.io.IOException: Access denied.
Code:
public class Test {
public static void main(String[] args) {
try {
StringBuilder sb = new StringBuilder(File.separator);
sb.append("index.txt");
// sb is "\\index.txt"
File f = new File(sb.toString());
boolean isCreated = f.createNewFile();
System.out.println(isCreated);
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Actually, I get it, I don't have permission to write a file there, but I am quite sure it can be done somehow. If I had an applet, I'd just obtain a permission, but here, I don't know how to do it.
The probable solution may be checking if I can write a file there, but to check it I might try to write a file first adn then delete it in order to check if it is possible to write a file there, but I don't find this solution an optimal way.
The easiest way to check is to use File.canWrite().
Having said that, it looks like you're writing into the root of the drive. On Windows that's probably not a good idea, and you may want to consider writing elsewhere - e.g. a temp dir.
I have written a method, that takes a String to a directory, and checks, whether you can write a file out there:
static boolean canWrite(String folderPath) {
File file = new File(folderPath);
String new_file = "HastaLaVistaBaby";
if (file.isDirectory()) {
try {
new File(file + "\\" + new_file).createNewFile();
} catch (IOException e) {
return false;
}
new File(file + "\\" + new_file).delete();
return true;
} else {
return false;
}
}
To improve it, you may check, whether file.isFile() and get a parent directory and call this method.
This line should be:
sb.append("C:\\index.txt");
The extra backslash escapes a backslash.
Whether you hard-code a file name, like I did, or you get a file name from the user, you need the full path and file name.