I have created EasyMock test cases for one method which has method.invoke().One test case runs fine with this code.The second one which should cover the first "if" condition creates this IlegalArguent Exception:Wrong number of arguments.I don't understand which one is incorrect.whether original code or test case.
Please help.
Original code:
#RequestMapping(value = "/invoke/{service}/{method}", method = RequestMethod.POST)
public #ResponseBody
Object invokeService(#PathVariable("service") String className,
#PathVariable("method") String method,
#RequestParam("ms") String signature,
#RequestParam("r") String responseType, #RequestBody String[] body)
throws Exception {
if (applicationContext != null
&& applicationContext.containsBean(className)) {
Object obj = applicationContext.getBean(className);
String temp[] = signature.split(",");
Object[] arguments = new Object[temp.length];
Class[] parameterTypes = new Class[temp.length];
for (int i = 0; i < temp.length; i++) {
if(temp[i] != null && !temp[i].isEmpty()) {
Class cls = Class.forName(temp[i]);
parameterTypes[i] = cls;
if (temp[i].startsWith("java.lang.")) {
arguments[i] = body[i];
} else {
try {
arguments[i] = mapper.readValue(body[i], cls);
} catch (Exception e) {
// e.printStackTrace();
arguments[i] = body[i];
}
}
}
}
Method m = null;
if(null !=signature && !signature.isEmpty()) {
m = obj.getClass().getMethod(method, parameterTypes);
} else {
m = obj.getClass().getMethod(method);
}
Object response = m.invoke(obj);
return response;
} else {
throw new Exception("ApplicationContext not properly set");
}
}
Test1(success):
#Test
public void testInvokeServiceNotJavaLang() throws Exception{
Object obj = new Object();
String[] body ={ "body" };
EasyMock.expect(applicationContext.containsBean("String")).andReturn(true);
EasyMock.expect(applicationContext.getBean("String")).andReturn(obj);
EasyMock.replay(applicationContext);
moduleInvocation.invokeService("String", "toString","", "responseType",body );
EasyMock.verify(applicationContext);
}
Test2(IllegalArgumentException:Wrong number of arguments)
#Test
public void testInvokeService() throws Exception{
Object obj = new Object();
String[] body ={ "body" };
EasyMock.expect(applicationContext.containsBean("Object")).andReturn(true);
EasyMock.expect(applicationContext.getBean("Object")).andReturn(obj);
EasyMock.replay(applicationContext);
moduleInvocation.invokeService("Object", "equals", "java.lang.Object", "responseType",body );
EasyMock.verify(applicationContext);
}
Problem is with your code, In first case you are calling a method String#toString() which does not have any parameters and it gets called successfully. In second case you are calling Object#equals() method which expects one argument as well so you need to pass that argument value as well while using m.invoke(), so your code should be for second case
m.invoke(obj,new Object[]{<object to be compared>});
and for fist case this will suffice
m.invoke(obj,null);
Hope this helps.
EDIT
You should write it something like this:
Method m = null;
if(null !=signature && !signature.isEmpty()) {
m = obj.getClass().getMethod(method, parameterTypes);
} else {
m = obj.getClass().getMethod(method);
arguments = null;
}
Object response = m.invoke(obj, arguments);
return response;
Related
`public Provider(String healthProvider) {
if (this.healthProvider == null) {
throw new IllegalArgumentException(PROVIDER_NULL);
}
if (this.healthProvider.isBlank()) {
throw new IllegalArgumentException(PROVIDER_ISBLANK);
}
this.healthProvider = healthProvider;
this.patients = new ArrayList<Patient>();
}
`
when placed like this, my preconditions for isBlank does pass but that of null passes
public Provider(String healthProvider) {
this.healthProvider = healthProvider;
this.patients = new ArrayList<Patient>();
if (this.healthProvider == null) {
throw new IllegalArgumentException(PROVIDER_NULL);
}
if (this.healthProvider.isBlank()) {
throw new IllegalArgumentException(PROVIDER_ISBLANK);
}
}
when i place the code like this my junit test passes but when i place the initialized data members after the preconditions, it doesnt pass.
Either would be fine, but your first should test the passed in healthProvider (since this.healthProvider isn't initialized yet, and when it is; it is using the passed healthProvider). Like,
public Provider(String healthProvider) {
if (healthProvider == null) {
throw new IllegalArgumentException(PROVIDER_NULL);
}
if (healthProvider.isBlank()) {
throw new IllegalArgumentException(PROVIDER_ISBLANK);
}
this.healthProvider = healthProvider;
this.patients = new ArrayList<Patient>();
}
I work with reflection. And I need to get the parameter method of my set () entity to call the corresponding fill method in accordance with the type.
try{
Class clazz = aClass.getClass();
Object object = clazz.newInstance();
while (clazz != Object.class){
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods){
if (method.isAnnotationPresent(ProductAnnotation.class)) {
Object[] strategyObj = new Object[1];
if (method.getReturnType().getName().equals("int")) { //reflexion never comes in if
strategyObj[0] = strategy.setInt(bundle.getString(method.getName().substring(3).toLowerCase()));
method.invoke(object, strategyObj);
}if (method.getParameterTypes().getClass().getTypeName().equals("String")){ //reflexion never comes in if
strategyObj[0] = strategy.setString(bundle.getString(method.getName().substring(3).toLowerCase()));
method.invoke(object, strategyObj);
}
}
}
clazz = clazz.getSuperclass();
}
return (FlyingMachine) object;
} catch (IllegalAccessException | IOException | InvocationTargetException | InstantiationException e) {
e.printStackTrace();
}
return null;
}
I tried to use getReturnedType () and getParametrTypes (), but the reflexion does not enter any condition. What was I wrong about?
My Annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(value = ElementType.METHOD)
public #interface ProductAnnotation {
String value();
}
Methods that should cause reflection.Depending on the type of method, call one of these methods for further processing and filling in the data.
#Override
public int setInt(String title) throws IOException {
String line = null;
checkValue = true;
while (checkValue) {
System.out.println(title + "-->");
line = reader.readLine();
if (line.matches("\\d*")) {
System.out.println(title + " = " + Integer.parseInt(line));
checkValue = false;
} else {
System.out.println("Wrong value, try again");
checkValue = true;
}
}
return Integer.parseInt(line);
}
setString() works exactly the same scheme.
Method::getParameterTypes returns Class[].
So your code method.getParameterTypes().getClass() will always return [Ljava.lang.Class. try this code:
Class[] types = method.getParameterTypes();
if (types.length == 1 && types[0] == String.class) {
// your second condition...
}
How do I prevent proguard from modifying the field names in my method?
I know we can use -keep, -keepclassmembers..etc but these seems to only preserve the member names and NOT the variables that are used inside.
Here's what happened:
Before:
private static URL getPluginImageURL(Object plugin, String name) throws Exception {
// try to work with 'plugin' as with OSGI BundleContext
try {
Class<?> BundleClass = Class.forName("org.osgi.framework.Bundle"); //$NON-NLS-1$
Class<?> BundleContextClass = Class.forName("org.osgi.framework.BundleContext"); //$NON-NLS-1$
if (BundleContextClass.isAssignableFrom(plugin.getClass())) {
Method getBundleMethod = BundleContextClass.getMethod("getBundle", new Class[0]); //$NON-NLS-1$
Object bundle = getBundleMethod.invoke(plugin, new Object[0]);
//
Class<?> PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$
Constructor<?> pathConstructor = PathClass.getConstructor(new Class[]{String.class});
Object path = pathConstructor.newInstance(new Object[]{name});
//
Class<?> IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$
Class<?> PlatformClass = Class.forName("org.eclipse.core.runtime.Platform"); //$NON-NLS-1$
Method findMethod = PlatformClass.getMethod("find", new Class[]{BundleClass, IPathClass}); //$NON-NLS-1$
return (URL) findMethod.invoke(null, new Object[]{bundle, path});
}
} catch (Throwable e) {
// Ignore any exceptions
}
// else work with 'plugin' as with usual Eclipse plugin
{
Class<?> PluginClass = Class.forName("org.eclipse.core.runtime.Plugin"); //$NON-NLS-1$
if (PluginClass.isAssignableFrom(plugin.getClass())) {
//
Class<?> PathClass = Class.forName("org.eclipse.core.runtime.Path"); //$NON-NLS-1$
Constructor<?> pathConstructor = PathClass.getConstructor(new Class[]{String.class});
Object path = pathConstructor.newInstance(new Object[]{name});
//
Class<?> IPathClass = Class.forName("org.eclipse.core.runtime.IPath"); //$NON-NLS-1$
Method findMethod = PluginClass.getMethod("find", new Class[]{IPathClass}); //$NON-NLS-1$
return (URL) findMethod.invoke(plugin, new Object[]{path});
}
}
return null;
}
After proguard:
private static URL getPluginImageURL(Object plugin, String name)
throws Exception
{
try
{
localClass1 = Class.forName("org.osgi.framework.Bundle");
localClass2 = Class.forName("org.osgi.framework.BundleContext");
if (localClass2.isAssignableFrom(plugin.getClass())) {
localObject1 = localClass2.getMethod("getBundle", new Class[0]);
localObject2 = ((Method)localObject1).invoke(plugin, new Object[0]);
localClass3 = Class.forName("org.eclipse.core.runtime.Path");
localObject3 = localClass3.getConstructor(new Class[] { String.class });
Object localObject4 = ((Constructor)localObject3).newInstance(new Object[] { name });
Class localClass4 = Class.forName("org.eclipse.core.runtime.IPath");
Class localClass5 = Class.forName("org.eclipse.core.runtime.Platform");
Method localMethod = localClass5.getMethod("find", new Class[] { localClass1, localClass4 });
return (URL)localMethod.invoke(null, new Object[] { localObject2, localObject4 });
}
}
catch (Throwable localThrowable)
{
Class localClass2;
Object localObject1;
Object localObject2;
Class localClass3;
Object localObject3;
Class localClass1 = Class.forName("org.eclipse.core.runtime.Plugin");
if (localClass1.isAssignableFrom(plugin.getClass()))
{
localClass2 = Class.forName("org.eclipse.core.runtime.Path");
localObject1 = localClass2.getConstructor(new Class[] { String.class });
localObject2 = ((Constructor)localObject1).newInstance(new Object[] { name });
localClass3 = Class.forName("org.eclipse.core.runtime.IPath");
localObject3 = localClass1.getMethod("find", new Class[] { localClass3 });
return (URL)((Method)localObject3).invoke(plugin, new Object[] { localObject2 });
}
}
return null;
}
Notice how localObject1 and localObject2 no longer have Class declaration? Doesn't this make the code syntactically incorrect?
Help...
It's your decompiler that produces the syntactically incorrect code. You could try a different decompiler.
ProGuard indeed removes the local variable names, since they are just optional debugging information. They are not required by the virtual machine.
I am trying to get the absolute URL in my managed bean's action listener. I have used:
HttpServletRequest#getRequestURL() // returning http://localhost:7101/POSM/pages/catalog-edit
HttpServetRequest#getQueryString() // returning _adf.ctrl-state=gfjk46nd7_9
But the actual URL is: http://localhost:7101/POSM/pages/catalog-edit?_adf.ctrl-state=gfjk46nd7_9&articleReference=HEN00067&_afrLoop=343543687406787. I don't know why the parameter artcileReference get omitted.
Is there any method which can give me the whole URL at once? How can I get the whole URL with all query string?
You can reconstruct your URL manually by using ServletRequest#getParameterNames() and ServletRequest#getParameter() both available with the HttpServletRequest instance.
Here is a sample code I've used in the past for this exact purpose :
private String getURL()
{
Enumeration<String> lParameters;
String sParameter;
StringBuilder sbURL = new StringBuilder();
Object oRequest = FacesContext.getCurrentInstance().getExternalContext().getRequest();
try
{
if(oRequest instanceof HttpServletRequest)
{
sbURL.append(((HttpServletRequest)oRequest).getRequestURL().toString());
lParameters = ((HttpServletRequest)oRequest).getParameterNames();
if(lParameters.hasMoreElements())
{
if(!sbURL.toString().contains("?"))
{
sbURL.append("?");
}
else
{
sbURL.append("&");
}
}
while(lParameters.hasMoreElements())
{
sParameter = lParameters.nextElement();
sbURL.append(sParameter);
sbURL.append("=");
sbURL.append(URLEncoder.encode(((HttpServletRequest)oRequest).getParameter(sParameter),"UTF-8"));
if(lParameters.hasMoreElements())
{
sbURL.append("&");
}
}
}
}
catch(Exception e)
{
// Do nothing
}
return sbURL.toString();
}
Here I came up with my solution, taking idea of the answer given by Alexandre, considering that HttpServletRequest#getParameterValues() method:
protected String getCurrentURL() throws UnsupportedEncodingException {
Enumeration parameters = getServletRequest().getParameterNames();
StringBuffer urlBuffer = new StringBuffer();
urlBuffer.append(getServletRequest().getRequestURL().toString());
if(parameters.hasMoreElements()) {
if(!urlBuffer.toString().contains("?")) {
urlBuffer.append("?");
} else {
urlBuffer.append("&");
}
}
while(parameters.hasMoreElements()) {
String parameter = (String)parameters.nextElement();
String[] parameterValues = getServletRequest().getParameterValues(parameter);
if(!CollectionUtils.sizeIsEmpty(parameterValues)) {
for(int i = 0; i < parameterValues.length; i++) {
String value = parameterValues[i];
if(StringUtils.isNotBlank(value)) {
urlBuffer.append(parameter);
urlBuffer.append("=");
urlBuffer.append(URLEncoder.encode(value, "UTF-8"));
if((i + 1) != parameterValues.length) {
urlBuffer.append("&");
}
}
}
}
if(parameters.hasMoreElements()) {
urlBuffer.append("&");
}
}
return urlBuffer.toString();
}
I have a strange java.lang.NullPointerException on a variable that should not be null.
Object[] params = new Object[10];
if (param1 != null)
params[0] = param1;
param1 is given as a method parameter, and it can be null.
Normally, when affecting param1 to params[0], it is not null (otherwise it won't pass the if statement).
Here is the error (line 144 is "params[0] = param1;"):
Exception in thread "Jalen Agent" java.lang.NullPointerException
at jalen.MethodStats.onMethodEntry(MethodStats.java:144)
at hanoi.TowersOfHanoi.solveHanoi(TowersOfHanoi.java)
at hanoi.TowersOfHanoi.main(TowersOfHanoi.java:29)
Here is the full code of the method where the exception occurs:
public static void onMethodEntry(int id, String className, String methodName, Object param1, Object param2, Object param3, Object param4, Object param5) {
synchronized (globalLock) {
Object[] params = new Object[10];
if (param1 != null)
params[0] = param1;
if (param2 != null)
params[1] = param2;
if (param3 != null)
params[2] = param3;
if (param4 != null)
params[3] = param4;
if (param5 != null)
params[4] = param5;
MethodStats.onMethodEntry(id, className, methodName, params);
}
}
EDIT:
To clarify my example, I am in a context of:
Instrument a Java application using ASM
Run the new instrumented classes while using a Java agent
The agent will use information collected by the instrumented code to run some measurements
The agent also collects the values of methods' parameters of the application.
For this, onMethodEntry is executed on each method run. I have several of these methods with different signatures. In particular:
public static void onMethodEntry(int id, String className, String methodName, Object[] params) {
synchronized (globalLock) {
StringBuilder fullMethodName = new StringBuilder(className).append('.').append(methodName).append('-').append(Thread.currentThread().getId());
MethodStats.addNewMethod(id, fullMethodName.toString());
System.out.println(fullMethodName.toString() + " -- " + id);
for (Object param : params) {
if (param != null)
System.out.println("Param: " + param.toString());
}
startTimes[depth] = System.nanoTime();
stack[depth++] = MethodStats.getMethodInfo(id);
}
}
public static void onMethodEntry(int id, String className, String methodName, Object param1) {
synchronized (globalLock) {
Object[] params = new Object[10];
if (param1 != null)
params[0] = param1;
MethodStats.onMethodEntry(id, className, methodName, params);
}
}
public static void onMethodEntry(int id, String className, String methodName, Object param1, Object param2) {
synchronized (globalLock) {
Object[] params = new Object[10];
if (param1 != null)
params[0] = param1;
if (param2 != null)
params[1] = param2;
MethodStats.onMethodEntry(id, className, methodName, params);
}
}
And this is the code I used for instrumenting the program classes (i.e. Tower of Hanoi):
public void visitCode() {
mv.visitLdcInsn(new Integer(this.methodID));
this.visitLdcInsn(this.className);
this.visitLdcInsn(this.methodName);
String paramCall = "";
if (this.numParam > 0) {
// Load parameters
for (int i=1; i<=this.numParam; i++) {
this.visitVarInsn(Opcodes.ALOAD, i);
paramCall += "Ljava/lang/Object;";
}
}
System.out.println(paramCall);
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
"jalen/MethodStats",
"onMethodEntry",
"(ILjava/lang/String;Ljava/lang/String;" + paramCall + ")V");
super.visitCode();
}
First, the error is not on the params[0] = param1 line, because the stack trace shows that your code entered the onMethodEntry method.
There is absolutely no point in adding if statements: in case param1 is null, there would be no null assignment, but params[0] would remain null because all unassigned positions in new Object[10] are initially set to null.
In order to fix the problem, you should first figure out what objects must be placed in the array instead of null parameters, and then modify the conditions as follows:
if (param1 != null) {
params[0] = param1;
} else {
params[0] = // something else
}
Why don't you replace your
onMethodEntry(int id, String className, String methodName, Object[] params) {
method with the varargs version:
onMethodEntry(int id, String className, String methodName, Object... params) {
That way, you can get rid of your other methods, which are all the same, just with different amount of parameters. Also the method containing your error would disappear. If the error still persists, you're one step closer to finding it.
Also, you wouldn't have to change any code where you call the method, because it's signature is the same.