/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.runtime;
import java.util.ResourceBundle;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.wst.server.core.IServer;
import org.jboss.ide.eclipse.as.management.core.IAS7ManagementDetails;
import org.osgi.framework.BundleContext;
import org.teiid.core.designer.PluginUtil;
import org.teiid.core.designer.event.IChangeNotifier;
import org.teiid.core.designer.util.PluginUtilImpl;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.workspace.ModelWorkspaceManager;
import org.teiid.designer.core.workspace.ModelWorkspaceNotification;
import org.teiid.designer.core.workspace.ModelWorkspaceNotificationAdapter;
import org.teiid.designer.extension.ExtensionPlugin;
import org.teiid.designer.extension.registry.ModelExtensionRegistry;
import org.teiid.designer.metamodels.relational.extension.RestModelExtensionAssistant;
import org.teiid.designer.metamodels.relational.extension.RestModelExtensionConstants;
import org.teiid.designer.runtime.spi.ITeiidServerManager;
/**
* The main plugin class to be used in the desktop.
*
* @since 8.0
*/
public class DqpPlugin extends Plugin {
/**
* This plugin's identifier.
*/
public static final String PLUGIN_ID = "org.teiid.designer.dqp"; //$NON-NLS-1$
/**
* The package identifier.
*/
public static final String PACKAGE_ID = DqpPlugin.class.getPackage().getName();
/**
* The name of the I18n properties file.
*/
private static final String I18N_NAME = PACKAGE_ID + ".i18n"; //$NON-NLS-1$
/**
* The source bindings file name
*/
public static final String SOURCE_BINDINGS_FILE_NAME = "SourceBindings.xml"; //$NON-NLS-1$
private static IPath runtimePath;
/**
* Provides access to the plugin's log and to it's resources.
*
* @since 4.2.1
*/
public static PluginUtil Util = new PluginUtilImpl(PLUGIN_ID, I18N_NAME, ResourceBundle.getBundle(I18N_NAME));
private ModelWorkspaceNotificationAdapter workspaceListener = null;
/**
* The shared instance.
*/
private static DqpPlugin plugin;
/**
* @return DqpPlugin
* @since 4.3
*/
public static DqpPlugin getInstance() {
return plugin;
}
/**
* Provider of the {@link IServer}s collection
*/
private IServersProvider serversProvider;
/**
* Obtains the current plugin preferences values.
*
* @return the preferences (never <code>null</code>)
*/
public IEclipsePreferences getPreferences() {
return this.getPreferences(PLUGIN_ID);
}
/**
* @return the jboss execution request timeout property from the preferences
* Note: the preference is saved in seconds while this will convert it into ms since
* that is what the {@link IAS7ManagementDetails#PROPERTY_TIMEOUT} requires
*/
public int getJbossRequestTimeout() {
IEclipsePreferences preferences = DqpPlugin.getInstance().getPreferences();
int timeout = preferences.getInt(PreferenceConstants.JBOSS_REQUEST_EXECUTION_TIMEOUT,
PreferenceConstants.JBOSS_REQUEST_EXECUTION_TIMEOUT_SEC_DEFAULT);
if (timeout < 100) {
// timeout preference is in seconds and the jboss property is in ms
timeout = timeout * 1000;
}
return timeout;
}
/**
* Obtains the current plugin preferences values for the given plugin id
*
* @param pluginId
*
* @return the preferences (never <code>null</code>) for the given plugin id
*/
public IEclipsePreferences getPreferences(String pluginId) {
return InstanceScope.INSTANCE.getNode(pluginId);
}
/**
* @return the <code>designer.dqp</code> plugin's runtime workspace path or the test runtime path
*
* @since 6.0.0
*/
public IPath getRuntimePath() {
if (runtimePath == null) {
runtimePath = DqpPlugin.getInstance().getStateLocation();
}
return (IPath)runtimePath.clone();
}
/**
* @return the server manager
*/
public ITeiidServerManager getServerManager() {
return ModelerCore.getTeiidServerManager();
}
/**
* Get the provider of the collection of {@link IServer}s
*
* @return servers provider
*/
public IServersProvider getServersProvider() {
if (serversProvider == null)
serversProvider = new DefaultServersProvider();
return serversProvider;
}
/**
* Cleans up the map of context helpers.
*
* @param theContext the context whose state has changed
* @since 4.3
*/
void handleContextChanged( final IChangeNotifier vdb ) {
// TODO: re-implement
// if (this.vdbHelperMap.get(vdb) != null) {
// // only care if the context is now closed
// if (!(vdb.isOpen()) {
// this.vdbHelperMap.remove(vdb);
// theContext.removeChangeListener(this.changeListener);
// }
// }
}
private void initializeDefaultPreferences() {
IEclipsePreferences prefs = DefaultScope.INSTANCE.getNode(DqpPlugin.getInstance().getBundle().getSymbolicName());
// initialize the Teiid cleanup enabled preference
prefs.putBoolean(PreferenceConstants.PREVIEW_ENABLED, PreferenceConstants.PREVIEW_ENABLED_DEFAULT);
// initialize the Teiid cleanup enabled preference
prefs.putBoolean(PreferenceConstants.PREVIEW_TEIID_CLEANUP_ENABLED,
PreferenceConstants.PREVIEW_TEIID_CLEANUP_ENABLED_DEFAULT);
}
/**
* Option names can be found in the <code>.debug</code> file and in {@link DebugConstants}.
*
* @param option the option being checked
* @return <code>true</code> if in debugging mode and the debug option is enabled
*/
public boolean isDebugOptionEnabled( String option ) {
return (isDebugging() && Boolean.toString(true).equals(Platform.getDebugOption(option)));
}
/**
* <p>
* {@inheritDoc}
* </p>
*
* @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
*/
@Override
public void start( final BundleContext context ) throws Exception {
super.start(context);
plugin = this;
// initialize logger first so that other methods can use logger
((PluginUtilImpl)Util).initializePlatformLogger(this);
// initialize preferences
initializeDefaultPreferences();
// register to receive workspace model events
this.workspaceListener = new ModelWorkspaceNotificationAdapter() {
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.workspace.ModelWorkspaceNotificationAdapter#notifyReloaded(org.teiid.designer.core.workspace.ModelWorkspaceNotification)
*/
@Override
public void notifyReloaded(ModelWorkspaceNotification notification) {
handleNewModelEvent(notification);
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.workspace.ModelWorkspaceNotificationAdapter#notifyAdd(org.teiid.designer.core.workspace.ModelWorkspaceNotification)
*/
@Override
public void notifyAdd(ModelWorkspaceNotification notification) {
handleNewModelEvent(notification);
}
};
ModelWorkspaceManager.getModelWorkspaceManager().addNotificationListener(this.workspaceListener);
}
/**
* {@inheritDoc}
* <p>
* It is recommended for the UI to call {@link TeiidServerManager#shutdown(org.eclipse.core.runtime.IProgressMonitor)} as there are
* shutdown tasks that the UI should block on before shutting down.
*
* @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
*/
@Override
public void stop( final BundleContext context ) throws Exception {
if (getServersProvider().isInitialised()) {
// If server is no longer initialised then no need to remove the listeners
getServersProvider().removeServerStateListener(TeiidParentServerListener.getInstance());
getServersProvider().removeServerLifecycleListener(TeiidParentServerListener.getInstance());
}
try {
if (getServerManager() != null) {
getServerManager().shutdown(null);
}
} finally {
super.stop(context);
}
}
/**
* @param notification the notification being handled (never <code>null</code>)
*/
void handleNewModelEvent(final ModelWorkspaceNotification notification) {
if (notification.isPostChange()) {
final IResource model = (IResource)notification.getNotifier();
if (model != null) {
final ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry();
final String prefix = RestModelExtensionConstants.NAMESPACE_PROVIDER.getNamespacePrefix();
final RestModelExtensionAssistant assistant = (RestModelExtensionAssistant)registry.getModelExtensionAssistant(prefix);
try {
assistant.applyMedIfNecessary(model);
} catch (Exception e) {
Util.log(e);
}
}
}
}
private static Display getDisplay() {
return (Display.getCurrent() == null ? Display.getDefault() : Display.getCurrent());
}
/**
* @param operation The operation to be executed in the SWT thread.
* @param asynchronous True if the operation should be run asynchronously, meaning the calling thread will not be blocked.
*/
private static void runInSwtThread( final Runnable operation, final boolean asynchronous ) {
Display display = getDisplay();
if (Thread.currentThread() != display.getThread()) {
if (asynchronous) {
display.asyncExec(operation);
} else {
display.syncExec(operation);
}
} else {
operation.run();
}
}
/**
* Convey the given exception to the user.
*
* @param ex
*/
public static void handleException(final Exception ex) {
/**
* TODO
* Not ideal as we are calling a UI dialog in a technically non-UI plugin.
* However, it already depends on org.eclipse.ui so free to use this stuff
* and displaying an error dialog is crucial to the user.
*/
Util.log(ex);
Runnable runnable = new Runnable() {
@Override
public void run() {
String reason = Util.getString("TeiidParentServerListener.initTeiidServerException.reason"); //$NON-NLS-1$
MultiStatus multiStatus = new MultiStatus(PLUGIN_ID, 0, reason, null);
Throwable throwable = ex;
do {
Status status = new Status(IStatus.ERROR, PLUGIN_ID, " * " + throwable.getLocalizedMessage()); //$NON-NLS-1$
multiStatus.add(status);
throwable = throwable.getCause();
} while (throwable != null);
StatusManager.getManager().handle(multiStatus, StatusManager.SHOW);
}
};
runInSwtThread(runnable, true);
}
}