blob: a94673a40b177655d350f5c73177708200cf3f3a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 BestSolution.at and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
******************************************************************************/
package org.eclipse.e4.tools.emf.ui.script.js;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.tools.emf.ui.common.IScriptingSupport;
import org.eclipse.e4.ui.services.IStylingEngine;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.PackageAdmin;
@SuppressWarnings({ "restriction", "deprecation" })
public class JavaScriptSupport implements IScriptingSupport {
public void openEditor(Shell shell, final Object mainElement, final IEclipseContext context) {
TitleAreaDialog dialog = new TitleAreaDialog(shell) {
private Text scriptField;
private Logger logger;
@Override
protected Control createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
logger = new Logger(getShell());
getShell().setText("Execute JavaScript");
setTitle("Execute JavaScript");
setMessage("Enter some JavaScript and execute it");
scriptField = new Text(container, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
scriptField.setLayoutData(new GridData(GridData.FILL_BOTH));
scriptField.setFont(JFaceResources.getTextFont());
return container;
}
@Override
protected void okPressed() {
execute(logger, mainElement, context, scriptField.getText());
}
@Override
protected Button createButton(Composite parent, int id,
String label, boolean defaultButton) {
return super.createButton(parent, id, id == IDialogConstants.OK_ID ? "Execute" : label, defaultButton);
}
};
dialog.open();
}
private void execute(Logger logger, Object mainElement, IEclipseContext context, String script) {
Context cx = Context.enter();
Scriptable sc = cx.initStandardObjects();
ScriptableObject.putProperty(sc, "mainObject", mainElement);
ScriptableObject.putProperty(sc, "eclipseContext", context);
ScriptableObject.putProperty(sc, "swt", new SWTSupport(Display.getCurrent()));
ScriptableObject.putProperty(sc, "service", new ServiceProvider(context));
ScriptableObject.putProperty(sc, "di", new DiProvider(context));
ScriptableObject.putProperty(sc, "log", logger);
try {
cx.evaluateString(sc, script, "<cmd>", 1, null);
} catch (Exception e) {
try {
logger.error(e);
} catch (Exception e1) {
}
}
}
public static class DiProvider {
private IEclipseContext context;
private PackageAdmin packageAdmin;
public DiProvider(IEclipseContext context) {
this.context = context;
}
public Object newInstance(String bundlename, String className) throws ClassNotFoundException {
Bundle bundle = getBundle(bundlename);
if( bundle != null ) {
Class<?> clazz = bundle.loadClass(className);
return ContextInjectionFactory.make(clazz, context);
}
return new IllegalArgumentException("Bundle '"+bundlename+"' is not known");
}
public Object execute(Object object) {
return ContextInjectionFactory.invoke(object, Execute.class, context);
}
public Object invokeByAnnotation(Object object, String bundlename, String className) throws ClassNotFoundException {
Bundle bundle = getBundle(bundlename);
if( bundle != null ) {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>) bundle.loadClass(className);
return ContextInjectionFactory.invoke(object, clazz, context);
}
return new IllegalArgumentException("Bundle '"+bundlename+"' is not known");
}
private Bundle getBundle(String bundlename) {
if( packageAdmin == null ) {
Bundle bundle = FrameworkUtil.getBundle(getClass());
BundleContext context = bundle.getBundleContext();
ServiceReference<PackageAdmin> reference = context.getServiceReference(PackageAdmin.class);
packageAdmin = context.getService(reference);
}
Bundle[] bundles = packageAdmin.getBundles(bundlename, null);
if (bundles == null)
return null;
// Return the first bundle that is not installed or uninstalled
for (int i = 0; i < bundles.length; i++) {
if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) {
return bundles[i];
}
}
return null;
}
}
public static class ServiceProvider {
private IEclipseContext context;
public ServiceProvider(IEclipseContext context) {
this.context = context;
}
public Object getStyleEngine() {
return context.get(IStylingEngine.class);
}
public Object getPartService() {
return context.get("org.eclipse.e4.ui.workbench.modeling.EPartService");
}
public Object getModelService() {
return context.get("org.eclipse.e4.ui.workbench.modeling.EModelService");
}
}
public static class Logger {
private Shell parentShell;
private Shell shell;
private Text text;
private static SimpleDateFormat DATEFORMAT = new SimpleDateFormat("hh:mm:ss.SSS");
public Logger(Shell parentShell) {
this.parentShell = parentShell;
}
public void openLog() {
if( shell == null ) {
shell = new Shell(parentShell,SWT.SHELL_TRIM);
shell.setLayout(new GridLayout());
text = new Text(shell, SWT.MULTI|SWT.BORDER|SWT.V_SCROLL|SWT.H_SCROLL);
text.setLayoutData(new GridData(GridData.FILL_BOTH));
text.setFont(JFaceResources.getTextFont());
text.setEditable(false);
shell.setVisible(true);
}
}
public void error(Object data) throws Exception {
_log(1, data);
}
public void debug(Object data) throws Exception {
_log(0, data);
}
private void _log(int type, Object data) throws Exception {
if( shell == null ) {
openLog();
}
shell.setVisible(true);
if( data instanceof Throwable ) {
StringWriter w = new StringWriter();
PrintWriter pw = new PrintWriter(w);
((Throwable)data).printStackTrace(pw);
text.append(DATEFORMAT.format(new Date()) + " - " + w + "\n");
pw.close();
w.close();
} else {
text.append(DATEFORMAT.format(new Date()) + " - " + data + "\n");
}
}
public void clearLog() {
if( text != null ) {
text.setText("");
}
}
public void closeLog() {
shell.dispose();
shell = null;
text = null;
}
}
public static class SWTSupport {
private Display d;
public static SWT SWT = new SWT();
public SWTSupport(Display d) {
this.d = d;
}
public Color newColor(String color) {
if( color.startsWith("#") ) {
if( color.length() == 7 ) {
return new Color(d, new RGB(
Integer.parseInt(color.substring(1,3), 16),
Integer.parseInt(color.substring(3,5), 16),
Integer.parseInt(color.substring(5,7), 16)));
} else {
return new Color(d, new RGB(
Integer.parseInt( color.charAt(1) + "" +color.charAt(1), 16),
Integer.parseInt( color.charAt(2) + "" +color.charAt(2), 16),
Integer.parseInt( color.charAt(3) + "" +color.charAt(3), 16)));
}
}
return null;
}
public Text newText(Composite parent, int style) {
return new Text(parent, style);
}
public Widget newLabel(Composite parent, int style) {
return new Label(parent, style);
}
public GridData newGridData() {
return new GridData();
}
public Combo newCombo(Composite parent, int style) {
return new Combo(parent, style);
}
}
}