/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.hibernate.eclipse.console;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationListener;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.JavaTextTools;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ltk.core.refactoring.CheckConditionsOperation;
import org.eclipse.ltk.core.refactoring.PerformRefactoringOperation;
import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.hibernate.console.ConsoleConfiguration;
import org.hibernate.console.HibernateConsoleRuntimeException;
import org.hibernate.console.KnownConfigurations;
import org.hibernate.console.KnownConfigurationsAdapter;
import org.hibernate.console.KnownConfigurationsListener;
import org.hibernate.console.preferences.ConsoleConfigurationPreferences;
import org.hibernate.eclipse.console.actions.AddConfigurationAction;
import org.hibernate.eclipse.console.utils.LaunchHelper;
import org.hibernate.eclipse.console.workbench.ConfigurationAdapterFactory;
import org.hibernate.eclipse.criteriaeditor.CriteriaEditorInput;
import org.hibernate.eclipse.criteriaeditor.CriteriaEditorStorage;
import org.hibernate.eclipse.hqleditor.HQLEditorInput;
import org.hibernate.eclipse.hqleditor.HQLEditorStorage;
import org.hibernate.eclipse.launch.ICodeGenerationLaunchConstants;
import org.hibernate.eclipse.launch.core.refactoring.ConsoleConfigurationRenameProcessor;
import org.hibernate.eclipse.logging.PluginLogger;
import org.hibernate.eclipse.logging.xpl.EclipseLogger;
import org.osgi.framework.BundleContext;
/**
* The main plugin class to be used in the desktop.
*/
public class HibernateConsolePlugin extends AbstractUIPlugin implements PluginLogger {
public static final String ID = "org.hibernate.eclipse.console"; //$NON-NLS-1$
static public final String LAST_USED_CONFIGURATION_PREFERENCE = "lastusedconfig"; //$NON-NLS-1$
public static final int PERFORM_SYNC_EXEC = 1;
//The shared instance.
private static HibernateConsolePlugin plugin;
//Resource bundle.
private ResourceBundle resourceBundle;
private EclipseLogger logger;
private JavaTextTools javaTextTools;
private ILaunchConfigurationListener icl;
private KnownConfigurationsListener kcl;
/**
* The constructor.
*/
public HibernateConsolePlugin() {
super();
setPlugin(this);
}
/**
* This method is called upon plug-in activation
*/
public void start(BundleContext context) throws Exception {
super.start(context);
logger=new EclipseLogger(context.getBundle());
//HibernateConsoleSaveParticipant participant = new HibernateConsoleSaveParticipant();
//participant.doStart(this);
IAdapterManager adapterManager = Platform.getAdapterManager();
ConfigurationAdapterFactory fact = new ConfigurationAdapterFactory();
fact.registerAdapters(adapterManager);
loadExistingConfigurations();
listenForConfigurations();
}
private void listenForConfigurations() {
final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
kcl = new KnownConfigurationsAdapter() {
/**
* @param root
* @param forUpdate - shows whether physical removal necessary
*/
public void configurationRemoved(ConsoleConfiguration root, boolean forUpdate) {
if(!forUpdate) {
try {
removeConfiguration(root.getName());
} catch (CoreException e) {
logErrorMessage(HibernateConsoleMessages.HibernateConsolePlugin_could_not_delete_launch_config_for + root.getName(), e);
}
}
}
};
KnownConfigurations.getInstance().addConsoleConfigurationListener(kcl);
icl = new ILaunchConfigurationListener() {
boolean isConsoleConfiguration(ILaunchConfiguration configuration) {
try {
return configuration.getType().getIdentifier().equals(ICodeGenerationLaunchConstants.CONSOLE_CONFIGURATION_LAUNCH_TYPE_ID);
}
catch (CoreException e) {
//HibernateConsolePlugin.getDefault().log( e );
// ignore since it occurs on delete
}
return false;
}
public void launchConfigurationRemoved(ILaunchConfiguration configuration) {
ConsoleConfiguration cfg = KnownConfigurations.getInstance().find( configuration.getName() );
if(cfg!=null) {
// file system removal have been made already.
KnownConfigurations.getInstance().removeConfiguration( cfg, true );
}
}
public void launchConfigurationChanged(ILaunchConfiguration configuration) {
if(configuration.isWorkingCopy() || isTemporary(configuration)) {
return;
}
if(isConsoleConfiguration( configuration )) {
KnownConfigurations instance = KnownConfigurations.getInstance();
ConsoleConfiguration oldcfg = instance.find( configuration.getName() );
if(oldcfg!=null) {
oldcfg.reset(); // reset it no matter what.
} else { // A new one!
ConsoleConfigurationPreferences adapter = buildConfigurationPreferences(configuration);
instance.addConfiguration(new ConsoleConfiguration(adapter), true);
}
}
}
private ConsoleConfigurationPreferences buildConfigurationPreferences(ILaunchConfiguration configuration) {
return new EclipseLaunchConsoleConfigurationPreferences(configuration);
}
public void launchConfigurationAdded(ILaunchConfiguration configuration) {
if(isConsoleConfiguration( configuration )) {
ILaunchConfiguration movedFrom = launchManager.getMovedFrom( configuration );
if(movedFrom!=null && isConsoleConfiguration( movedFrom )) {
KnownConfigurations instance = KnownConfigurations.getInstance();
ConsoleConfiguration oldcfg = instance.find( movedFrom.getName() );
if(oldcfg!=null) {
refactor(movedFrom, configuration);//call this before we remove old configuration
oldcfg.reset(); // reset it no matter what.
instance.removeConfiguration(oldcfg, false);
}
}
KnownConfigurations instance = KnownConfigurations.getInstance();
ConsoleConfigurationPreferences adapter = buildConfigurationPreferences(configuration);
boolean temporary = isTemporary(configuration);
if(!temporary) {
instance.addConfiguration(new ConsoleConfiguration(adapter), true);
}
}
}
private void refactor (ILaunchConfiguration oldConfiguration, ILaunchConfiguration newConfiguration) {
if (!oldConfiguration.getName().equals(newConfiguration.getName())){
//only rename of console configuration refactoring is supported.
ConsoleConfigurationRenameProcessor proc = new ConsoleConfigurationRenameProcessor(oldConfiguration, newConfiguration.getName());
// Refactor for rename
PerformRefactoringOperation refOperation = new PerformRefactoringOperation(
new ProcessorBasedRefactoring(proc),
CheckConditionsOperation.ALL_CONDITIONS);
try
{
ResourcesPlugin.getWorkspace().run(refOperation, null);
}
catch (OperationCanceledException oce)
{
throw new OperationCanceledException();
}
catch (CoreException ce)
{
HibernateConsolePlugin.openError(new Shell(), HibernateConsoleMessages.EditConsoleConfiguration_rename_refactoring_error_totle,
ce.getLocalizedMessage(), ce, HibernateConsolePlugin.PERFORM_SYNC_EXEC);
}
}
}
private boolean isTemporary(ILaunchConfiguration configuration) {
boolean temporary = true;
try {
temporary = configuration.getAttribute(AddConfigurationAction.TEMPORARY_CONFIG_FLAG, false);
} catch (CoreException e) {
HibernateConsolePlugin.getDefault().showError( getShell(), HibernateConsoleMessages.HibernateConsolePlugin_problem_to_get_flag, e);
}
return temporary;
}
};
launchManager.addLaunchConfigurationListener( icl );
}
private void stopListeningForConfigurations() {
final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
launchManager.removeLaunchConfigurationListener( icl );
KnownConfigurations.getInstance().removeConfigurationListener(kcl);
}
private void loadExistingConfigurations() throws CoreException {
ILaunchConfiguration[] launchConfigurations = LaunchHelper.findHibernateLaunchConfigs();
for (int i = 0; i < launchConfigurations.length; i++) {
KnownConfigurations.getInstance().addConfiguration(
new ConsoleConfiguration(new EclipseLaunchConsoleConfigurationPreferences(launchConfigurations[i])), false );
}
}
/**
* Remove configuration from the file system.
* @param name
* @throws CoreException
*/
private void removeConfiguration(String name) throws CoreException {
ILaunchConfiguration findLaunchConfig = findLaunchConfig(name);
if (findLaunchConfig != null) {
findLaunchConfig.delete();
}
}
public ILaunchConfiguration findLaunchConfig(String name)
throws CoreException {
return LaunchHelper.findHibernateLaunchConfig(name);
}
/**
* This method is called when the plug-in is stopped
*/
public void stop(BundleContext context) throws Exception {
super.stop(context);
stopListeningForConfigurations();
setPlugin(null);
resourceBundle = null;
}
/**
* Returns the shared instance.
*/
public static HibernateConsolePlugin getDefault() {
return plugin;
}
private static void setPlugin(HibernateConsolePlugin plugin) {
HibernateConsolePlugin.plugin = plugin;
}
/**
* Returns the string from the plugin's resource bundle,
* or 'key' if not found.
*/
public static String getResourceString(String key) {
ResourceBundle bundle = HibernateConsolePlugin.getDefault().getResourceBundle();
try {
return (bundle != null) ? bundle.getString(key) : key;
} catch (MissingResourceException e) {
return key;
}
}
/**
* Returns the plugin's resource bundle,
*/
public ResourceBundle getResourceBundle() {
try {
if (resourceBundle == null)
resourceBundle = ResourceBundle.getBundle("org.hibernate.eclipse.console.HibernateConsolePluginResources"); //$NON-NLS-1$
} catch (MissingResourceException x) {
resourceBundle = null;
}
return resourceBundle;
}
/**
* Logs the specified status with this plug-in's log.
*
* @param status status to log
*/
public void log(IStatus status) {
logger.log(status);
}
/**
* Logs an internal info with the specified message.
*
* @param message the error message to log
*/
public void log(String message) {
log(new Status(IStatus.INFO, HibernateConsolePlugin.ID, 0, message, null) );
}
/**
* Logs an internal error with the specified message.
*
* @param message the error message to log
*/
public void logErrorMessage(String message, Throwable t) {
logMessage(IStatus.ERROR, message, t);
}
public void logMessage(int lvl, String message, Throwable t) {
if(t==null) {
log(message);
} else {
log(new MultiStatus(HibernateConsolePlugin.ID, lvl , new IStatus[] { throwableToStatus(t) }, message, null));
}
}
public static IStatus throwableToStatus(Throwable t, int code) {
List<IStatus> causes = new ArrayList<IStatus>();
Throwable temp = t;
while(temp!=null && temp.getCause()!=temp) {
causes.add(new Status(IStatus.ERROR, ID, code, temp.getMessage()==null?temp.toString() + HibernateConsoleMessages.HibernateConsolePlugin_no_message_1:temp.toString(), temp) );
temp = temp.getCause();
}
String msg = HibernateConsoleMessages.HibernateConsolePlugin_no_message_2;
if(t!=null && t.getMessage()!=null) {
msg = t.toString();
}
if(causes.isEmpty()) {
return new Status(IStatus.ERROR, ID, code, msg, t);
} else {
return new MultiStatus(ID, code,causes.toArray(new IStatus[causes.size()]), msg, t);
}
}
public static IStatus throwableToStatus(Throwable t) {
return throwableToStatus(t, 150);
}
public void logErrorMessage(String message, Throwable t[]) {
IStatus[] children = new IStatus[t.length];
for (int i = 0; i < t.length; i++) {
Throwable throwable = t[i];
children[i] = throwableToStatus(throwable);
}
IStatus s = new MultiStatus(ID, 150,children, message, null);
log(s);
}
/**
* Logs an internal error with the specified throwable
*
* @param e the exception to be logged
*/
public void log(Throwable e) {
log(new Status(IStatus.ERROR, ID, 150, "Hibernate Console Internal Error", e) ); //$NON-NLS-1$
}
void readStateFrom(File f) {
try {
EclipseConsoleConfigurationPreferences[] preferences = EclipseConsoleConfigurationPreferences.readStateFrom(f);
for (int i = 0; i < preferences.length; i++) {
ConsoleConfigurationPreferences prefs = preferences[i];
KnownConfigurations.getInstance().addConfiguration(new EclipseConsoleConfiguration(prefs), false); // TODO: do we need to broadcast every time when reading state ?
}
} catch(HibernateConsoleRuntimeException hcr) {
logErrorMessage(HibernateConsoleMessages.HibernateConsolePlugin_error_while_reading_console_config, hcr);
}
}
void writeStateTo(File f) {
//System.out.println("write state to" + f);
KnownConfigurations.getInstance().writeStateTo(f);
}
/**
*
*/
public void showError(Shell shell, String message, Throwable he) {
logErrorMessage(message, he);
IStatus warning = throwableToStatus(he);
ErrorDialog.openError(shell,
HibernateConsoleMessages.HibernateConsolePlugin_hibernate_console, message, warning);
}
public void showError(Shell shell, String message, IStatus s) {
log(s);
ErrorDialog.openError(shell,
HibernateConsoleMessages.HibernateConsolePlugin_hibernate_console, message, s);
}
public IEditorPart openCriteriaEditor(String consoleName, String criteria) {
try {
IWorkbenchPage page = getActiveWorkbenchWindow().getActivePage();
CriteriaEditorStorage storage = new CriteriaEditorStorage(consoleName, criteria==null?"":criteria); //$NON-NLS-1$
final CriteriaEditorInput editorInput = new CriteriaEditorInput(storage);
return page.openEditor(editorInput, "org.hibernate.eclipse.criteriaeditor.CriteriaEditor", true); //$NON-NLS-1$
//page.openEditor(editorInput, "org.eclipse.jdt.ui.CompilationUnitEditor", true);
} catch (PartInitException ex) {
logErrorMessage(HibernateConsoleMessages.HibernateConsolePlugin_could_not_open_criteria_editor_for_console + consoleName, ex);
return null;
}
}
public IEditorPart openScratchHQLEditor(String consoleName, String hql) {
try {
IWorkbenchPage page = getActiveWorkbenchWindow().getActivePage();
HQLEditorStorage storage = new HQLEditorStorage(consoleName, hql==null?"":hql); //$NON-NLS-1$
final HQLEditorInput editorInput = new HQLEditorInput(storage);
return page.openEditor(editorInput, "org.hibernate.eclipse.hqleditor.HQLEditor", true); //$NON-NLS-1$
} catch (PartInitException ex) {
logErrorMessage(HibernateConsoleMessages.HibernateConsolePlugin_could_not_open_hql_editor_for_console + consoleName, ex);
return null;
}
}
/*public ConsoleConfiguration getLastUsedConfiguration() {
String lastUsedName = getDefault().getPreferenceStore().getString(HibernateConsolePlugin.LAST_USED_CONFIGURATION_PREFERENCE);
ConsoleConfiguration lastUsed = (lastUsedName == null || lastUsedName.trim().length()==0)
? null
: KnownConfigurations.getInstance().find(lastUsedName);
if(lastUsed==null && KnownConfigurations.getInstance().getConfigurations().length==1) {
lastUsed = KnownConfigurations.getInstance().getConfigurations()[0];
}
return lastUsed;
}*/
/*public void setLastUsedConfiguration(ConsoleConfiguration lastUsed) {
String name;
if(lastUsed==null) {
name = "";
} else {
name = lastUsed.getName();
}
HibernateConsolePlugin.getDefault().getPreferenceStore().setValue(
LAST_USED_CONFIGURATION_PREFERENCE, name );
}*/
/**
* Convenience method for showing an error dialog
* @param shell a valid shell or null
* @param exception the exception to be report
* @param title the title to be displayed
* @param flags customizing attributes for the error handling
* @return IStatus the status that was displayed to the user
*/
public static IStatus openError(Shell providedShell, String title, String message, Throwable exception, int flags) {
// Unwrap InvocationTargetExceptions
if (exception instanceof InvocationTargetException) {
Throwable target = ((InvocationTargetException)exception).getTargetException();
// re-throw any runtime exceptions or errors so they can be handled by the workbench
if (target instanceof RuntimeException) {
throw (RuntimeException)target;
}
if (target instanceof Error) {
throw (Error)target;
}
return openError(providedShell, title, message, target, flags);
}
// Determine the status to be displayed (and possibly logged)
IStatus status = null;
if (exception instanceof CoreException) {
status = ((CoreException)exception).getStatus();
} else if (exception != null) {
status = new MultiStatus(ID, IStatus.ERROR, new IStatus[] { throwableToStatus(exception.getCause())}, exception.toString(), exception);
}
// Check for multi-status with only one child
/*if (status.isMultiStatus() && status.getChildren().length == 1) {
status = status.getChildren()[0]; // makes Status.ERROR - Status.OK
}*/
if (status.isOK()) {
return status;
}
// Create a runnable that will display the error status
final String displayTitle = title;
final String displayMessage = message;
final IStatus displayStatus = status;
final IOpenableInShell openable = new IOpenableInShell() {
public void open(Shell shell) {
if (displayStatus.getSeverity() == IStatus.INFO && !displayStatus.isMultiStatus()) {
MessageDialog.openInformation(shell, "Information", displayStatus.getMessage()); //$NON-NLS-1$
} else {
ErrorDialog.openError(shell, displayTitle, displayMessage, displayStatus);
}
}
};
openDialog(providedShell, openable, flags);
// return the status we display
return status;
}
/**
* Open the dialog code provided in the IOpenableInShell, ensuring that
* the provided whll is valid. This method will provide a shell to the
* IOpenableInShell if one is not provided to the method.
*
* @param providedShell
* @param openable
* @param flags
*/
public static void openDialog(Shell providedShell, final IOpenableInShell openable, int flags) {
// If no shell was provided, try to get one from the active window
if (providedShell == null) {
IWorkbenchWindow window = getDefault().getWorkbench().getActiveWorkbenchWindow();
if (window != null) {
providedShell = window.getShell();
// sync-exec when we do this just in case
flags = flags | PERFORM_SYNC_EXEC;
}
}
// Create a runnable that will display the error status
final Shell shell = providedShell;
Runnable outerRunnable = new Runnable() {
public void run() {
Shell displayShell;
if (shell == null) {
Display display = Display.getCurrent();
displayShell = new Shell(display);
} else {
displayShell = shell;
}
openable.open(displayShell);
if (shell == null) {
displayShell.dispose();
}
}
};
// Execute the above runnable as determined by the parameters
if (shell == null || (flags & PERFORM_SYNC_EXEC) > 0) {
Display display;
if (shell == null) {
display = Display.getCurrent();
if (display == null) {
display = Display.getDefault();
}
} else {
display = shell.getDisplay();
}
display.syncExec(outerRunnable);
} else {
outerRunnable.run();
}
}
/**
* Interface that allows a shell to be passed to an open method. The
* provided shell can be used without sync-execing, etc.
*/
public interface IOpenableInShell {
public void open(Shell shell);
}
public static Shell getShell() {
if (getActiveWorkbenchWindow() != null) {
return getActiveWorkbenchWindow().getShell();
}
return null;
}
public static IWorkbenchWindow getActiveWorkbenchWindow() {
return getDefault().getWorkbench().getActiveWorkbenchWindow();
}
public JavaTextTools getJavaTextTools() {
if (javaTextTools == null) {
javaTextTools = new JavaTextTools(PreferenceConstants.getPreferenceStore());
}
return javaTextTools;
}
public static ImageDescriptor getImageDescriptor(String path) {
return AbstractUIPlugin.imageDescriptorFromPlugin(ID, path);
}
public void logWarning(Exception he) {
logMessage(IStatus.WARNING, he==null?null:he.getMessage(), he);
}
}