Accessing JAVA classes and functions from CFML - Object instantiation exception - java

I want to access a JAVA function from CFML script:
<cfscript>
authToken = createobject("java","coldfusion.security.SecurityManager").createAuthToken('admin', 'cfadmin', '12345', false);
</cfscript>
<cfoutput>authToken: #authToken#</cfoutput>
I got the following error:
Object instantiation exception.
An exception occurred while instantiating a Java object. The class
must not be an interface or an abstract class. If the class has a
constructor that accepts an argument, you must call the constructor
explicitly using the init(args) method. Error :
coldfusion.security.SecurityManager
I know is because the arguments passed directly to createAuthToken that I can't do and I should init() it. How can I correctly pass the arguments in this scenario?

It pretty much tells you what you need to do in the error message. But for the sake of clarity:
<cfset authToken = createobject("java","coldfusion.security.SecurityManager")
.init() // you might need some init() args here?
.createAuthToken('admin', 'cfadmin', '12345', false)
>
I'm not really sure why you bother to put that sinple statement into a <cfscript> block, btw. Would not a <cfset> do?

Related

Unable to correctly initialize xml-security library using ColdFusion 10.0

I am using the following to initialize in CF 10 and I placed the xmlsec-1.5.8.jar file under Coldfusion10/cfusion/lib
<cfset Init = CreateObject("Java", "org.apache.xml.security.Init.Init()")>
I have also tried placing the above code in a cfscript as
Init = CreateObject("Java", "org.apache.xml.security.Init.Init()");
I am getting the following error.
You must initialize the xml-security library correctly before you use it. Call the static method "org.apache.xml.security.Init.init();" to do that before you use any functionality from that library.
Thank you.
In addition to the syntax error, there is another problem. The error message is indicating you must call a static method of that class first. One that is literally named init(). The problem is init() has a special meaning in CF. CF does not allow using the new keyword with java objects. Instead, it uses the name init() as a pseudo-constructor, which allows you to create a new instance of a class. So when you do this:
obj = createObject("java", "org.apache.xml.security.Init").init();
CF will create a new instance of that class, NOT call a method named init(). AFAIK, the only way around it is to use reflection. Something along these lines:
// get a reference to the class
ref = createObject("java", "org.apache.xml.security.Init");
// initialize if needed
if (!ref.isInitialized()) {
// find static method named "init" with no parameters
method = ref.getClass().getDeclaredMethod("init", []);
// invoke it via reflection
method.invoke(ref, javacast("null", ""));
}
placed the xmlsec-1.5.8.jar file under Coldfusion10/cfusion/lib
While there is nothing wrong with doing that, as of CF10, you can also load jars dynamically via your Application settings, ie this.javaSettings. If the feature seems familiar, it is basically a rip of Mark Mandel's awesome JavaLoader.cfc, only baked into CF ;-)

I don't understand the call to the parent class from within the class in this JAVA class

Can you help me understand why we call the parent class here? I found a download class that seemed simple enough but could use help wrapping my brain around the first method.
public class DownloadHandler {
public static void main(String[] args) throws Exception {
DownloadHandler d = new DownloadHandler();
d.URLSetUp(args[0]);
}
....
}
I am trying to instantiate the handler in a for loop and getting an error.
DownloadHandler file = new DownloadHandler("http://example.com/"+cleanLink+"/"+filename+".pdf")
It says "DownloadHandler() in DownloadHandler cannot be applied to (java.lang.String)"
Your DownloadHandler class has a static void main method, which is the single point of entry when executing command-line programs.
That method is not a constructor.
What it does is initialize a new instance of DownloadHandler and invoking an instance method on that object by passing the given String argument.
Not sure what's the usage there.
In order for your initialization to compile, you probably want to add a constructor that performs similar operations, given a single String parameter in your case.
For instance:
public DownloadHandler(String s) {
URLSetUp(s);
}
Java adds a default constructor to every class that doesn't provide one. A constructor is a method without a return type. So, in your case the default constructor DownloadHandler() is automatically added to your class and it does not take any parameters while you are trying to initialize it with a String.
The String you are using in main method right now is coming from console from user.
From your code its obvious that you want to pass a argument via command line parameter. But when you are initiating DownloadHandler, you are passing that string here which is not you should be doing.
There are two things you can do now.
Pass the string via command line parameter
java DownloadHandler yourstring
Write a constructor which accepts the string. In your code outside of your main method
String url;
public DownloadHandler(String str)
{
url = str;
}
Now call
d.URLSetup(url);
Hope this will clear your doubts.

Mocking a method with possible null values in powermock

I have a method which does the following as a part of the operation:
URL resourceUrl = new File(sampleString1.concat("/")
.concat(sampleString2)).toURI().toURL();
SampleString1 and SampleString2 are populated by the constructor of the class and the class is an abstract class. I used the below line to test this class:
servlet = PowerMockito.mock(MyServlet.class, Mockito.CALLS_REAL_METHODS);
Through this i'm unable to set values of attributes sampleString1 and sampleString2 as i'm not passing them to constructor. Now, when i call my test method in servlet, i get NullPointerExceptions at the above mentioned line because of null values at sampleString1 and sampleString2. I tried to simulate that part by the following:
PowerMockito.whenNew(File.class).withParameterTypes(String.class).
withArguments(Matchers.anyString()).thenReturn(sampleFile);
but still it goes through the string concatanations when new file call is done and throws exception. How can i test this method? I just want to return a sample value for resourceUrl when new file operation is called and proceed with the logic in the method and test the output.
Thanks.
You can use the Whitebox API documented at the following locations:
http://code.google.com/p/powermock/wiki/BypassEncapsulation
http://powermock.googlecode.com/svn/docs/powermock-1.4.12/apidocs/org/powermock/reflect/Whitebox.html
It uses reflection to set the values on an object like so:
MyServlet servlet = PowerMockito.mock(MyServlet.class, Mockito.CALLS_REAL_METHODS);
Whitebox.setInternalState(servlet, "sampleString1", "foo");
Whitebox.setInternalState(servlet, "sampleString2", "bar");
//Test code...

how do I use a class when I only find out its name in a string variable at run time?

Is there a way to run class X's methods from another class (in the same project but different package) when I only have class X's name stored in a String - say I don't know what classes exist until my program starts and I scan the directory for .java files then store those names into Strings.
So for example I have class A, which has functions 'main' and 'method1' - my program gets the name of class A from its file into String s. Then I want to be able to run the main or method1 functions but am unsure how to manipulate s to get there...one thing I've tried is this but I simply get the Exception error and don't know if it's on the right track, any suggestions?:
//gets the filename from JFileChooser method_fc
File file = method_fc.getSelectedFile();
try {
Class c = Class.forName(file.getName());
Method method = c.getDeclaredMethod("main");
Object instance = c.newInstance ();
Object result = method.invoke(instance);
} catch (Exception e) {
System.out.println("Cannot access class: "+e.getMessage());
}
You can do that but take into consideration that class name does not end with ".java" or ".class" (you can remove it).
My guess is that your main method has a String[] parameter, but you're not supplying it - or it's a static method, but you're trying to call it as an instance method.
However, it's hard to tell without seeing with the class or the error message.
As Fernando notes, the name of the class isn't the same as the name of the file - not only would a filename end in ".class", but there might also be packages involved - a file "Foo.class" may actually contain a class "com.acme.Foo".
EDIT: As noted in comments, the class will also need to be in the classpath, or a special ClassLoader will be required.
main is usually a static method with a String[] parameter. If so, you don't need an instance - use the Class object itself as the target object.
This fragment works on a standard main method:
Class<?> c = Class.forName("com.company.SomeClass");
Method method = c.getDeclaredMethod("main", String[].class);
method.invoke(c, (Object) new String[] {});
please report the full stack of the exception.
I guess that your main method receive as parameter at least an array of string. Furthermore the main method usually doesn't return any result because it is defined as void.
Why didn't you pass args to the method invoke?
String[] args = new String[1]
Object result = method.invoke(instance, args);
Please report at least the declaration of the main method.
Regards,
Luca

Getting method via reflection

My previous post was not very clear, sorry for that. I will try to give a better example of what I am trying to do.
I have an Java application that will load .class files and runs them in a special enviroment (the Java app has built-in functions) Note: This is not a library.
That Java application will then display an applet, and I want to modify the variables in the applet.
The main class of the applet is called 'client'.
The Java application will load the applet by creating an new instance of class 'client'.
I already got access to the 'client' class. the Java application will put the applet in a variable:
Applet client = (Applet) loadedClientClass.newInstance();
So I did this:
Class<?> class_client = client.getClass();
I can now read and set the fields but the 'client' class will call a funation of an other class, like this:
otherClass.someVoid(false);
And if I try something like:
class_client.getDeclaredMethod("otherClass.someVoid",boolean.class);
It will fail, saying that the function can not be found.
'otherClass' is the direct class name, it is not a reference to a new instance of the class as far as I know.
Is there any way to get 'otherClass.someVoid'?
You're using getDeclaredMethod like a static method (expecting it to return methods from any class), but it only returns method from the class itself. Here's how you can call otherClass.someVoid(false).
Class<?> otherClass = Class.forName("com.xyz.OtherClass"); // Get the class
Method method = otherClass.getDeclaredMethod("someVoid", boolean.class);
// If the method is an Class (ie static) method, invoke it on the Class:
method.invoke(otherClass, false);
// If the method is an instance (ie non-static) method, invoke it on an instance of the Class:
Object otherInstance = otherClass.newInstance(); // Get an instance of other class - this approach assumes there is a default constructor
method.invoke(otherInstance, false);
If the class isn't initialized, the var someInteger doesn't exist. It's a member variable, so it only exists inside of instances of the class. So, you can't change it since it's doesn't exist. Now, if you made it a static variable, then you could change it.
Is there any way to change 'otherClass.someInteger' through the
'mainClass' class?
No.
But you can get it via OtherClass' class via Class.forName:
Class<?> theOtherClazz = Class.forName("OtherClass");
And then get the methods via theOtherClazz.getDeclaredMethod

Categories