blob: a11aa87dfcb6d05c649515b28181826bbf0b5e66 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2002, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.cheatsheets;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.help.internal.entityresolver.LocalEntityResolver;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
/**
* The main plugin class for cheat sheets.
*/
public class CheatSheetPlugin extends AbstractUIPlugin {
public final static String PLUGIN_ID = "org.eclipse.help.base"; //$NON-NLS-1$
//The shared instance of this plugin.
static CheatSheetPlugin plugin;
//Resource bundle.
//private boolean resourceBundleInitialized = false;
//private ResourceBundle resourceBundle;
private CheatSheetHistory history = null;
private DocumentBuilder documentBuilder = null;
private static final String HISTORY_FILENAME = "history.xml"; //$NON-NLS-1$
private static final String MEMENTO_TAG_CHEATSHEET = "cheatsheet"; //$NON-NLS-1$
private static final String MEMENTO_TAG_VERSION = "version"; //$NON-NLS-1$
private static final String VERSION_STRING[] = { "0.0", "3.0.0" }; //$NON-NLS-1$ //$NON-NLS-2$
private static final String MEMENTO_TAG_CHEATSHEET_HISTORY = "cheatsheetHistory"; //$NON-NLS-1$
public static final IPath ICONS_PATH = new Path("$nl$/icons/"); //$NON-NLS-1$
public static final String T_OBJ = "obj16/"; //$NON-NLS-1$
public static final String T_ELCL = "elcl16/"; //$NON-NLS-1$
public static final String T_DLCL = "dlcl16/"; //$NON-NLS-1$
public static final String T_VIEW = "view16/"; //$NON-NLS-1$
/**
* The constructor.
*/
public CheatSheetPlugin() {
super();
}
/**
* Returns the shared instance.
*/
public static CheatSheetPlugin getPlugin() {
return plugin;
}
/**
* Returns the image in Cheat Sheet's image registry with the given key,
* or <code>null</code> if none.
* Convenience method equivalent to
* <pre>
* CheatSheetPlugin.getImageRegistry().get(key)
* </pre>
*
* @param key the key
* @return the image, or <code>null</code> if none
*/
public Image getImage(String key) {
Image image = getImageRegistry().get(key);
return image;
}
/**
* Returns the CheatSheetHistory
*/
public CheatSheetHistory getCheatSheetHistory() {
if (history == null) {
history = new CheatSheetHistory(CheatSheetRegistryReader.getInstance());
restoreCheatSheetHistory();
}
return history;
}
/**
* Get a file from the state folder.
*/
private File getCheatSheetStateFile(String filename) {
IPath path = CheatSheetPlugin.getPlugin().getStateLocation();
path = path.append(filename);
return path.toFile();
}
/**
* Returns the DocumentBuilder to be used by the cheat sheets.
*/
public DocumentBuilder getDocumentBuilder() {
if(documentBuilder == null) {
try {
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
documentBuilder.setEntityResolver(new LocalEntityResolver());
} catch (Exception e) {
IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, Messages.ERROR_CREATING_DOCUMENT_BUILDER, e);
CheatSheetPlugin.getPlugin().getLog().log(status);
}
}
return documentBuilder;
}
/**
* Logs an Error message with an exception.
*/
public static synchronized void logError(String message, Throwable ex) {
if (message == null)
message = ""; //$NON-NLS-1$
Status errorStatus = new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK,
message, ex);
CheatSheetPlugin.getPlugin().getLog().log(errorStatus);
}
@Override
protected void initializeImageRegistry(ImageRegistry reg) {
IPath path = ICONS_PATH.append(T_OBJ).append("cheatsheet_obj.gif");//$NON-NLS-1$
ImageDescriptor imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_OBJ, imageDescriptor);
path = ICONS_PATH.append(T_OBJ).append("skip_status.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_ITEM_SKIP, imageDescriptor);
path = ICONS_PATH.append(T_OBJ).append("complete_status.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_ITEM_COMPLETE, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("linkto_help.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_ITEM_HELP, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("start_cheatsheet.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_START, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("restart_cheatsheet.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_RESTART, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("start_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_START, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("skip_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_SKIP, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("complete_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_COMPLETE, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("restart_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_RESTART, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("return_to_start.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_RETURN, imageDescriptor);
path = ICONS_PATH.append(T_OBJ).append("error.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.ERROR, imageDescriptor);
// Images used by composites
path = ICONS_PATH.append(T_OBJ).append("composite_obj.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.COMPOSITE_OBJ, imageDescriptor);
path = ICONS_PATH.append(T_OBJ).append("information.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.INFORMATION, imageDescriptor);
path = ICONS_PATH.append(T_OBJ).append("warning.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.WARNING, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("start_ccs_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.COMPOSITE_TASK_START, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("skip_ccs_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.COMPOSITE_TASK_SKIP, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("review_ccs_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.COMPOSITE_TASK_REVIEW, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("goto_ccs_task.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.COMPOSITE_GOTO_TASK, imageDescriptor);
path = ICONS_PATH.append(T_ELCL).append("restart_all.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.COMPOSITE_RESTART_ALL, imageDescriptor);
path = ICONS_PATH.append(T_VIEW).append("cheatsheet_view.gif");//$NON-NLS-1$
imageDescriptor = createImageDescriptor(getPlugin().getBundle(), path);
reg.put(ICheatSheetResource.CHEATSHEET_VIEW, imageDescriptor);
}
/**
* Restores the state of the previously saved cheatsheet history
*/
private void restoreCheatSheetHistory() {
SafeRunner.run(new SafeRunnable() {
@Override
public void run() {
IMemento memento;
memento = readMemento(HISTORY_FILENAME);
if (memento != null) {
IMemento childMem = memento.getChild(MEMENTO_TAG_CHEATSHEET_HISTORY);
if (childMem != null) {
history.restoreState(childMem);
}
}
}
@Override
public void handleException(Throwable e) {
String message = Messages.ERROR_READING_STATE_FILE;
IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, message, e);
CheatSheetPlugin.getPlugin().getLog().log(status);
}
});
}
/**
* Read a memento from the state directory for the cheatsheets plugin
* @param filename A simple filename
* @return A memento read from the state directory or null if the memento could not be read
*/
public XMLMemento readMemento(String filename) {
XMLMemento memento;
InputStreamReader reader = null;
try {
// Read the cheatsheet state file.
final File stateFile = getCheatSheetStateFile(filename);
FileInputStream input = new FileInputStream(stateFile);
reader = new InputStreamReader(input, StandardCharsets.UTF_8);
memento = XMLMemento.createReadRoot(reader);
} catch (FileNotFoundException e) {
memento = null;
// Do nothing, the file will not exist the first time the workbench in used.
} catch (Exception e) {
String message = Messages.ERROR_READING_STATE_FILE;
IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, message, e);
CheatSheetPlugin.getPlugin().getLog().log(status);
memento = null;
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
// Not much to do, just catch the exception and keep going.
String message = Messages.ERROR_READING_STATE_FILE;
IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, message, e);
CheatSheetPlugin.getPlugin().getLog().log(status);
}
}
return memento;
}
/**
* Saves the current cheatsheet history so it can be restored later on
*/
private void saveCheatSheetHistory() {
SafeRunner.run(new SafeRunnable() {
@Override
public void run() {
XMLMemento memento = XMLMemento.createWriteRoot(MEMENTO_TAG_CHEATSHEET);
// Save the version number.
memento.putString(MEMENTO_TAG_VERSION, VERSION_STRING[1]);
// Save perspective history.
getCheatSheetHistory().saveState(memento.createChild(MEMENTO_TAG_CHEATSHEET_HISTORY));
IStatus status = saveMemento(memento, HISTORY_FILENAME);
if (!status.isOK()) {
CheatSheetPlugin.getPlugin().getLog().log(status);
}
}
@Override
public void handleException(Throwable e) {
String message = Messages.ERROR_WRITING_STATE_FILE;
IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, message, e);
CheatSheetPlugin.getPlugin().getLog().log(status);
}
});
}
/**
* Save the memento to a file in this plugins state area
* @param memento The memento to save
* @param filename A simple filename
* @return OK_Status if the memento was saved without error, otherwise an error
* status
*/
public IStatus saveMemento(XMLMemento memento, String filename) {
// Save the IMemento to a file.
File stateFile = getCheatSheetStateFile(filename);
OutputStreamWriter writer = null;
try {
FileOutputStream stream = new FileOutputStream(stateFile);
writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
memento.save(writer);
return Status.OK_STATUS;
} catch (IOException e) {
stateFile.delete();
String message = Messages.ERROR_WRITING_STATE_FILE;
IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, message, e);
return status;
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException e) {
String message = Messages.ERROR_WRITING_STATE_FILE;
IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, message, e);
CheatSheetPlugin.getPlugin().getLog().log(status);
}
}
}
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
// allow the MRU history to be lazily initialized by getCheatSheetHistory
}
@Override
public void stop(BundleContext context) throws Exception {
super.stop(context);
// save the MRU history if necessary
// if we never restored history, let existing memento stand
if (history != null) {
saveCheatSheetHistory();
}
CheatSheetRegistryReader.getInstance().stop();
}
/*
* Since 3.1.1. Load from icon paths with $NL$
*/
public static ImageDescriptor createImageDescriptor(Bundle bundle, IPath path) {
URL url= FileLocator.find(bundle, path, null);
if (url != null) {
return ImageDescriptor.createFromURL(url);
}
return null;
}
}