2016-07-23 12 views
0

hallo Stackoverflow-Community,Access-Schnittstelle eines benutzerdefinierten Eclipse-Plugin zur Laufzeit

Ich habe eine benutzerdefinierte Eclipse-Plugin, die die Schnittstelle

public interface IMatchResultEvaluator { 

    String evaluateMatchResult(MatchResult match); 
} 

definiert.

Jetzt möchte ich der Benutzer in der Lage sein, diese Schnittstelle zur Laufzeit zu implementieren. Also möchte ich, dass er den Code für die Methode evaluateMatchResult über eine GUI schreiben kann, dann möchte ich seine Klasse mit dem Java 6-Compiler api kompilieren und dann möchte ich die Klasse mithilfe von Reflektion laden. Um dies zu tun, müsste ich zur Laufzeit auf die Klasse IMatchResultEvaluator zugreifen. Wie geht das?

Mit Hilfe der Antwort des Svasa versuchte ich bereits den javac-Compiler aufzurufen, die

Bundle bundle = Platform.getBundle("com.florian.regexfindandreplace"); 
    String bundleLocation = bundle.getLocation(); 
    String[] locs = bundleLocation.split("reference:file:/"); 
    String interfaceFileLoc = locs[1] + bundle.getEntry("/IMatchResultEvaluator"); 

    ProcessBuilder processBuilder = new ProcessBuilder(javaCompiler.getAbsolutePath(), "-classpath", 
interfaceFileLoc, myImplFile.getAbsolutePath()); 
      Process p = processBuilder.start(); 

Art und Weise aber, dass kompilieren nicht, weil das Symbol IMatchResultEvaluator nicht gefunden wurde. Was muss ich hier ändern?

Danke für jede Hilfe.

+0

Wie sieht die GUI aus? Es enthält eine Texteingabe für den Implementierungskörper von 'evaluateMatchResult'? – SomeDude

+0

Ja, Sie haben die Idee. – user172501

Antwort

0

Ich würde über so etwas gehen: Ich nehme an, Benutzer würde nur den Körper der Implementierung in der GUI eingeben, und Sie kennen den vollständigen Pfad der Schnittstelle.

try 
{ 
    Class<?> IMatchResultEvaluator = Class.forName("UI.IMatchResultEvaluator"); 
    String userText = "My Implementation"; 
    String MyImplClass = "public class MyImplClass implements " + IMatchResultEvaluator.getSimpleName() + "\n" + "{" + "\n" + "@Override String evaluateMatchResult(MatchResult match)" + "\n" + "{ " + "\n" + userText + "\n" + " }" + "\n" + "}"; 


    File myImplFile = createMyImplClass(MyImplClass); 
    if (myImplFile != null & myImplFile.exists()) 
    { 
     compileClass(myImplFile); 
    } 

} 
catch (ClassNotFoundException e) 
{ 
    e.printStackTrace(); 
} 

private File createMyImplClass(String MyImplClass) 
{ 
    File file = new File("MyImplClass.java"); 

    //write to file from string MyImplClass 
    return file; 
} 

private void compileClass(File file) 
{ 
    //Get full path of interface 
    Bundle bundle = Platform.getBundle("<your plugin qualified name>"); 
    String bundleLocation = bundle.getLocation(); 
    String[] locs = bundleLocation.split("reference:file:/"); 
    String interfaceFileLoc = locs[1] + bundle.getEntry("/IMatchResultEvaluator"); 


    //Compile class 

} 
+0

In der CompileClass-Methode muss ich der javac.exe mitteilen, wo die IMatchResultEvaluator-Schnittstelle zu finden ist. Daher muss der Klassenpfad korrekt festgelegt werden. Wie macht man das? – user172501

+0

Ich hoffe, Sie kennen den voll qualifizierten Namen von IMatchResultEvaluator, um es in 'Class.forName (...)' zu übergeben, über den vollständigen Pfad der Schnittstelle, um javac.exe mitzuteilen, siehe aktualisierte 'compileClass'-Methode, aber ich dachte Sie haben bereits eine Interface-Klasse geladen, nein? – SomeDude

+0

poste was 'locs [1]' in deinem env anzeigt, auch brauchst du nicht 'interfacefileloc' in classpath, nur' locs [1] ' – SomeDude

0

Ich habe endlich das Problem gelöst. Ich kompilieren nur diese Klasse jetzt

public class MyImplClass { 
public static String evaluateMatch(MatchResult match){ 
userText 
} 
} 

und dann habe ich kompilieren und laden Sie diese Klasse in die Variable clazz vom Typ Klasse und machen diese

  final Method method = clazz.getMethod("evaluateMatch", MatchResult.class); 
      return new IMatchEvaluator() 
        { 

         @Override 
         public String evaluateMatch(MatchResult match) { 
          try { 
           return (String) method.invoke(null, match); 
          } catch (Exception e) { 
           System.err.println(e.getMessage()); 
           return null; 
          } 
         } 

        }; 

Wenn jemand wollte, er konnte mein Plugin von https://marketplace.eclipse.org/content/findreplace-regular-expressions-and-match-evaluators herunterladen .