blob: a1077985a511f210f9a4ba52a2f56411496f9391 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation 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:
* Dean Roberts, IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.examples.webintegration.orion.editor.plugin;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IStorageEditorInput;
/**
* This class implements the call in point for a web application.
* Through this single BrowserFunction a web application can request
* various actions.
*
* An alternate implementation could have a a single BrowserFunction subclass
* for each action a web application could call. But it was unclear that
* such an implementation adds any value.
*/
public class EditorService extends BrowserFunction {
// Action constants. Same values used by JavaScript
private static final int DIRTY_CHANGED = 1;
private static final int GET_CONTENT_NAME = 2;
private static final int GET_INITIAL_CONTENT = 3;
private static final int SAVE = 4;
private static final int STATUS_CHANGED = 5;
// Name of the JavaScript variable containing the editor service
public static final String EDITOR_SERVICE_MAP = "editorService";
// Name of the JavaScript function for the editor service handler
public static final String EDITOR_SERVICE_HANDLER = "editorServiceHandler";
// Name of JavaScript save function
public static final String JAVA_SCRIPT_SAVE_FUNCTION = "return " + EDITOR_SERVICE_MAP + ".save()";
Editor editor;
public EditorService(Browser browser, String name, Editor editor) {
super(browser, name);
this.editor = editor;
}
/**
* This is the single function that is invoked by the JavaScript program.
* By specification of our implementation there is always one or more arguments
* and the first argument is the action id.
* Subsequent arguments, if present, are arguments for the given action.
*/
public Object function(Object[] arguments) {
super.function(arguments);
if (arguments.length == 0 || !(arguments[0] instanceof Double)) {
return null;
}
int action = ((Double) arguments[0]).intValue();
switch (action) {
case DIRTY_CHANGED:
return doDirtyChanged(arguments);
case GET_CONTENT_NAME:
return doGetContentName(arguments);
case GET_INITIAL_CONTENT:
return doGetInitialContent(arguments);
case SAVE:
return doSave(arguments);
case STATUS_CHANGED:
return doStatusChanged(arguments);
default:
return null;
}
}
// Actions
/**
* Return the initial content for the editor. Return an empty string on any error
*/
private Object doGetInitialContent(Object[] arguments) {
if (editor.getEditorInput() instanceof IStorageEditorInput) {
IStorageEditorInput input = (IStorageEditorInput) editor.getEditorInput();
BufferedInputStream inputStream = null;
try {
IStorage storage = input.getStorage();
inputStream = new BufferedInputStream(storage.getContents());
String contents = readInputStream(inputStream);
return contents;
} catch (CoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return "";
}
/**
* Return the name of the file being edited. Return an empty string on any error
*/
private Object doGetContentName(Object[] arguments) {
if (editor.getEditorInput() instanceof IFileEditorInput) {
IFileEditorInput input = (IFileEditorInput) editor.getEditorInput();
return input.getName();
}
return "";
}
/**
* This method is called by the JavaScript editor whenever its dirty state changes.
* Set the dirty status of the Eclipse editor so the framework displays the
* appropriate dirty marker and save actions are enabled appropriately.
*
* Return the dirtyState after the event is processed
*/
private Object doDirtyChanged(Object[] arguments) {
if (arguments.length == 2 && (arguments[1] instanceof Boolean)) {
editor.setDirty((Boolean) arguments[1]);
}
return editor.isDirty();
}
/**
* JavaScript has requested a save. Call the Eclipse editors save method.
* By contract, the JavaScript passes the new contents as an argument.
* @param arguments
* @return
*/
private Object doSave(Object[] arguments) {
boolean result = false;
if (arguments.length == 2 && (arguments[1] instanceof String)) {
String newContents = (String) arguments[1];
result = editor.performSave(newContents);
}
return result;
}
/**
* Update Eclipse status line.
* Currently we dig the cursor position out of the string that the Orion editor sends us.
* Clearly we would prefer Orion API that could just send us the position info ... but this is, after all,
* a web integration example and not an Orion example :-)
*/
private boolean doStatusChanged(Object[] arguments) {
if (arguments.length != 2 || !(arguments[1] instanceof String)) {
return false;
}
String[] position = parsePosition((String) arguments[1]);
editor.setPositionStatus(position[0] + " : " + position[1]);
return true;
}
// Boring utility methods
// Read all the bytes from an InputStream and return them as a String
private String readInputStream(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = null;
buffer = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int bytesRead = 0;
while ((bytesRead = inputStream.read(bytes)) != -1) {
buffer.write(bytes, 0, bytesRead);
}
return buffer.toString();
}
// Really sleazy "parsing" code for "Line x : Col y". Lots of error cases ignored
private String[] parsePosition(String message) {
int start = message.indexOf("Line ") + "Line ".length();
int end = message.indexOf(' ', start);
String line = message.substring(start, end);
start = message.indexOf("Col ") + "Col ".length();
end = message.indexOf(' ', start);
if (end == -1) {
end = message.length();
}
String col = message.substring(start, end);
return new String[] {line, col};
}
}