0

I'm trying to write a function that receives a string that consists of a static method with a string array as an argument.

For example, let's imagine we have this class with a static method:

package com.stack.examples;

public class Example {

   public static void testMethod() {
       System.out.println("method executed");
    }
}

Now, our function would be in another class, as follows:

package com.stack.functions;

public class Functions {

   public void parseCommand(String command) {
      //TODO, this is where my doubts lie
      //The given string is always composed of a sequence of Java identifiers 
        //separated by the character ’.’, representing the full qualified name of 
          //a Java method (package.class.method)
       command.execute(); //Would this work? Perhaps reflection would be ideal

   }
}

My objective is to parse the string given as an argument in parseCommand so that

parseCommand("com.stack.examples.Example.testMethod()");

actually calls the static method with the given arguments (in this example case, the method would only print out "message executed").

Maslor
  • 1,821
  • 3
  • 20
  • 44
  • I had this question posted before but it was automatically shut down as it was considered a "duplicate" of a question that didn't even have an answer other than "go check plugin x, go check compiler y". When I finally found the answer to my question, I couldn't answer as it was locked. Therefore, and since my reopen request hasn't been heard, I deleted the questions and asked it again here with my provided answer as I think that someone might benefit from this answer. – Maslor May 11 '16 at 12:14

2 Answers2

1

After searching for alternatives to solve this problem, I found that reflection worked out for me:

Static method to be executed:

package test;

public class Example {
    public static void testMethod() {
        System.out.println("method executed");
    }
}

Main Class:

package test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {

    public static void reflectVulnerableMethod(String str) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
                    IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        String[] parts = str.split("\\.");

        String forKlazz = "";
        for (int i=0; i<parts.length -1; i++) {
            if (i != 0){
                forKlazz += '.' + parts[i];
            }
            else forKlazz += parts[i];
        }
        Class<?> klazz = Class.forName(forKlazz);
        Method m = klazz.getMethod(parts[parts.length-1]);


        m.invoke(null);


    }

    public static void main(String[] args) {
        try {
            reflectVulnerableMethod("test.Example.testMethod");
        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException
                | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
Community
  • 1
  • 1
Maslor
  • 1,821
  • 3
  • 20
  • 44
  • 2
    Disclaimer: Doing this in a strongly typed language like Java goes against its design philosophy, so make sure you have a *very* good reason before you start to abuse reflection like this. – Kayaman May 11 '16 at 12:13
  • What is the alternative to doing this? I agree that it seems like this isn't the best answer to the problem but I haven't been able to find a more viable solution :/ @Kayaman – Maslor May 11 '16 at 12:18
  • 1
    It depends on the *actual* problem. If your problem really is "I need to call a method from a `String`", then this is the solution. However usually there's the original problem and the developer thinks that the *only* way is to use reflection. – Kayaman May 11 '16 at 12:20
0

Use Java reflects: First search for a equaly named method in your Example class and then invoke it. Maybe also check your Methods parameters method.getParameters()

    Method[] methods = Example.class.getMethods();
    for (Method method : methods) {
        if(method.getName().equals(command)){
            try {
                method.invoke(Example.class, null);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
Mad Matts
  • 1,118
  • 10
  • 14