Skip to content

Instantly share code, notes, and snippets.

@serge1
Last active February 17, 2017 10:00
Show Gist options
  • Save serge1/082be1138bce8f52270675fc923fc72b to your computer and use it in GitHub Desktop.
Save serge1/082be1138bce8f52270675fc923fc72b to your computer and use it in GitHub Desktop.
Eclipse View project that demonstrates JavaScript and Java dynamic compilation and inter operability
package jstest.views;
import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.security.SecureClassLoader;
import java.util.ArrayList;
import java.util.List;
// Based on: http://javapracs.blogspot.cz/2011/06/dynamic-in-memory-compilation-using.html
public class DynamicCompiler {
//private static final Logger logger = LoggerFactory.getLogger(DynamicCompiler.class);
private JavaFileManager fileManager;
private String fullName;
private String sourceCode;
public DynamicCompiler(String fullName, String srcCode) {
this.fullName = fullName;
this.sourceCode = srcCode;
this.fileManager = initFileManager();
}
public JavaFileManager initFileManager() {
if (fileManager != null)
return fileManager;
else {
System.setProperty("java.home", "c:\\Program Files (x86)\\Java\\jdk1.8.0_92");
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
fileManager = new
ClassFileManager(compiler
.getStandardFileManager(null, null, null));
return fileManager;
}
}
public void compile() {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<JavaFileObject> files = new ArrayList<>();
files.add(new CharSequenceJavaFileObject(fullName, sourceCode));
compiler.getTask(
null,
fileManager,
null,
null,
null,
files
).call();
}
public Class<?> get() {
Class<?> ret = null;
try {
ret = fileManager
.getClassLoader(null)
.loadClass(fullName);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ret;
}
public void run() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
try {
fileManager
.getClassLoader(null)
.loadClass(fullName)
.getDeclaredMethod("main", new Class[]{String[].class})
.invoke(null, new Object[]{null});
} catch (InvocationTargetException e) {
System.out.print("InvocationTargetException");
//logger.error("InvocationTargetException:", e);
} catch (NoSuchMethodException e) {
System.out.print("NoSuchMethodException ");
//logger.error("NoSuchMethodException:", e);
}
}
public class CharSequenceJavaFileObject extends SimpleJavaFileObject {
/**
* CharSequence representing the source code to be compiled
*/
private CharSequence content;
public CharSequenceJavaFileObject(String className, CharSequence content) {
super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
this.content = content;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return content;
}
}
@SuppressWarnings("rawtypes")
public class ClassFileManager extends ForwardingJavaFileManager {
private JavaClassObject javaClassObject;
@SuppressWarnings("unchecked")
public ClassFileManager(StandardJavaFileManager standardManager) {
super(standardManager);
}
@Override
public ClassLoader getClassLoader(Location location) {
return new SecureClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] b = javaClassObject.getBytes();
return super.defineClass(name, javaClassObject.getBytes(), 0, b.length);
}
};
}
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
this.javaClassObject = new JavaClassObject(className, kind);
return this.javaClassObject;
}
}
public class JavaClassObject extends SimpleJavaFileObject {
protected final ByteArrayOutputStream bos =
new ByteArrayOutputStream();
public JavaClassObject(String name, Kind kind) {
super(URI.create("string:///" + name.replace('.', '/')
+ kind.extension), kind);
}
public byte[] getBytes() {
return bos.toByteArray();
}
@Override
public OutputStream openOutputStream() throws IOException {
return bos;
}
}
}
- Start a wizard for new Eclipse Plug-in Project
- Give project name "jstest"
- Select "Plug-in with a view"
- Give a View Class Name "JSTestView" (and use "Table viewer")
- Substitute the generated source files and add the files from here
package jstest.views;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.part.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import java.util.ArrayList;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.eclipse.ui.*;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
/**
* This sample class demonstrates how to plug-in a new workbench view. The view
* shows data obtained from the model. The sample creates a dummy model on the
* fly, but a real implementation would connect to the model available either in
* this or another plug-in (e.g. the workspace). The view is connected to the
* model using a content provider.
* <p>
* The view uses a label provider to define how model objects should be
* presented in the view. Each view can present the same model objects using
* different labels and icons, if needed. Alternatively, a single label provider
* can be shared between views in order to ensure that objects of the same type
* are presented in the same way everywhere.
* <p>
*/
public class JSTestView extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "jstest.views.JSTestView";
private TableViewer viewer;
private final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
private final ArrayList<String> array = new ArrayList<String>();
private ArrayList<String> arrayToShow;
private Text filter;
private Text filter1;
private final MySelectionListener mySelectionListener = new MySelectionListener();
private final MySelectionListener1 mySelectionListener1 = new MySelectionListener1();
class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
public String getColumnText(Object obj, int index) {
return getText(obj);
}
public Image getColumnImage(Object obj, int index) {
return getImage(obj);
}
public Image getImage(Object obj) {
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT);
}
}
/**
* The constructor.
*/
public JSTestView() {
array.add("One");
array.add("Two");
array.add("Three");
array.add("Four");
array.add("Five");
array.add("Six");
arrayToShow = array.stream().collect(Collectors.toCollection(ArrayList::new));
}
private static Boolean safeInvokeFunction(Invocable invocable, String param1, String param2) {
try {
return (Boolean) invocable.invokeFunction(param1, param2);
} catch (NoSuchMethodException | ScriptException e) {
// e.printStackTrace();
}
return false;
}
/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
public void createPartControl(Composite parent) {
GridLayout layout = new GridLayout(3, false);
parent.setLayout(layout);
Label filterLabel = new Label(parent, SWT.NONE);
filterLabel.setText("Filter: ");
filter = new Text(parent, SWT.BORDER | SWT.SEARCH);
filter.addSelectionListener(mySelectionListener);
final Button filterApplyButton = new Button(parent, SWT.PUSH);
filterApplyButton.setText("Apply JavaScript");
filterApplyButton.addSelectionListener(mySelectionListener);
filter.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
Label filterLabel1 = new Label(parent, SWT.NONE);
filterLabel1.setText("Filter: ");
filter1 = new Text(parent, SWT.BORDER | SWT.SEARCH);
filter1.addSelectionListener(mySelectionListener1);
filter1.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
final Button filterApplyButton1 = new Button(parent, SWT.PUSH);
filterApplyButton1.setText("Apply Java");
filterApplyButton1.addSelectionListener(mySelectionListener1);
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setInput(arrayToShow);
viewer.setLabelProvider(new ViewLabelProvider());
GridData gridData = new GridData();
gridData.verticalAlignment = GridData.FILL;
gridData.horizontalSpan = 3;
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
gridData.horizontalAlignment = GridData.FILL;
viewer.getControl().setLayoutData(gridData);
// Create the help context id for the viewer's control
PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), "jstest.viewer");
getSite().setSelectionProvider(viewer);
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
viewer.getControl().setFocus();
}
private class MySelectionListener implements SelectionListener {
@Override
public void widgetSelected(SelectionEvent e) {
doIt();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
doIt();
}
private void doIt() {
String condition = filter.getText();
condition = condition.trim();
if (condition.isEmpty()) {
condition = "true";
}
String myScript = "";
myScript += "var checkIt = function(text) {";
myScript += " if (" + condition + ")";
myScript += " return true;";
myScript += " else";
myScript += " return false;";
myScript += "}";
try {
engine.eval(myScript);
Invocable invocable = (Invocable) engine;
arrayToShow = array.stream().filter(t -> safeInvokeFunction(invocable, "checkIt", t))
.collect(Collectors.toCollection(ArrayList::new));
viewer.setInput(arrayToShow);
} catch (ScriptException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
private class MySelectionListener1 implements SelectionListener {
@Override
public void widgetSelected(SelectionEvent e) {
doIt();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
doIt();
}
/**
*
*/
private void doIt() {
String condition = filter1.getText();
condition = condition.trim();
if (condition.isEmpty()) {
condition = "true";
}
String className = "jstest.views.MyJavaFilter";
String code = ""
+ "package jstest.views;\n"
+ "import java.util.function.Predicate;\n"
+ "public class MyJavaFilter implements Predicate<String> {\n"
+ " @Override\n"
+ " public boolean test(String value) {\n"
+ " if (" + condition + ")\n"
+ " return true;\n"
+ " else\n"
+ " return false;\n"
+ " }\n"
+ "}\n";
DynamicCompiler compiler = new DynamicCompiler(className, code);
compiler.compile();
try {
Class<?> myClass = compiler.get();
@SuppressWarnings("unchecked")
Predicate<String> myTest = (Predicate<String>) myClass.newInstance();
arrayToShow = array.stream()
.filter(myTest)
.collect(Collectors.toCollection(ArrayList::new));
viewer.setInput(arrayToShow);
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment