/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2006 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** 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.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.ui.internal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.InternalOwl;
import org.rssowl.core.util.LoggingSafeRunnable;
import org.rssowl.core.util.LongOperationMonitor;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.BindException;
/**
* The main plugin class to be used in the desktop.
*/
public class Activator extends AbstractUIPlugin {
/** ID of this Plugin */
public static final String PLUGIN_ID = "org.rssowl.ui"; //$NON-NLS-1$
/* Singleton Instance of this Plugin */
private static Activator fgPlugin;
private Thread fShutdownHook;
/**
* The constructor.
*/
public Activator() {
fgPlugin = this;
}
/**
* This method is called upon plug-in activation
*/
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
/*
* Start internal Server (chance that System.exit() gets called!). It is cruicial
* that no class from org.rssowl.core is loaded to avoid that a second instance
* that is launching, starts up the core for a second time.
*/
SafeRunner.run(new ISafeRunnable() {
public void run() throws Exception {
startServer();
}
public void handleException(Throwable e) {
if (e instanceof CoreException)
Activator.getDefault().getLog().log(((CoreException) e).getStatus());
}
});
/* Register a Shutdown Hook */
fShutdownHook = new Thread() {
@Override
public void run() {
/* Shutdown UI */
SafeRunner.run(new LoggingSafeRunnable() {
public void run() throws Exception {
Controller.getDefault().shutdown(true);
}
});
/* Shutdown Core */
SafeRunner.run(new LoggingSafeRunnable() {
public void run() throws Exception {
Owl.getPersistenceService().shutdown(true);
}
});
}
};
fShutdownHook.setPriority(Thread.MAX_PRIORITY);
Runtime.getRuntime().addShutdownHook(fShutdownHook);
/* Activate the Core Bundle */
SafeRunner.run(new LoggingSafeRunnable() {
public void run() throws Exception {
startCore();
}
});
/* Propagate startup to Controller */
SafeRunner.run(new LoggingSafeRunnable() {
public void run() throws Exception {
Controller.getDefault().startup();
}
});
/* Propagate post-ui startup to Controller */
SafeRunner.run(new LoggingSafeRunnable() {
public void run() throws Exception {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
Controller.getDefault().postUIStartup();
}
});
}
});
}
private void startCore() {
/* Dialog to show progress */
final ProgressMonitorDialog dialog = new ProgressMonitorDialog(new Shell(Display.getDefault())) {
@Override
protected Point getInitialLocation(Point initialSize) {
Rectangle displayBounds = getParentShell().getDisplay().getPrimaryMonitor().getBounds();
Point shellSize = getInitialSize();
int x = displayBounds.x + (displayBounds.width - shellSize.x) >> 1;
int y = displayBounds.y + (displayBounds.height - shellSize.y) >> 1;
return new Point(x, y);
}
@Override
protected Point getInitialSize() {
int minWidth = 380;
int minHeight = getShell().computeSize(minWidth, SWT.DEFAULT).y;
return new Point(minWidth, minHeight);
}
@Override
protected Control createButtonBar(Composite parent) {
return null;
}
};
dialog.setOpenOnRun(false);
/* Runnable to start core */
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
LongOperationMonitor callbackMonitor = new LongOperationMonitor(monitor) {
@Override
public void beginLongOperation() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
dialog.open();
}
});
}
};
/* Start Core */
InternalOwl.getDefault().startup(callbackMonitor);
}
};
/* Execute the Runnable */
try {
dialog.run(false, false, runnable);
} catch (InvocationTargetException e) {
Activator.getDefault().logError(e.getMessage(), e);
} catch (InterruptedException e) {
Activator.getDefault().logError(e.getMessage(), e);
}
}
/* Start the Application Server */
private void startServer() {
ApplicationServer server = ApplicationServer.getDefault();
try {
server.startup();
}
/* Server alredady bound - perform hand-shake */
catch (BindException e) {
logError(e.getMessage(), e);
}
/* Log any IOException */
catch (IOException e) {
logError(e.getMessage(), e);
}
}
/**
* This method is called when the plug-in is stopped
*/
@Override
public void stop(BundleContext context) throws Exception {
/* Remove Shutdown Hook first that would run too otherwise */
Runtime.getRuntime().removeShutdownHook(fShutdownHook);
/* Propagate shutdown to Controller */
SafeRunner.run(new LoggingSafeRunnable() {
public void run() throws Exception {
Controller.getDefault().shutdown(false);
}
});
/* Proceed */
super.stop(context);
fgPlugin = null;
}
/**
* Returns the shared instance.
*
* @return The shared instance.
*/
public static Activator getDefault() {
return fgPlugin;
}
/**
* Returns an image descriptor for the image file at the given plug-in
* relative path.
*
* @param path the path
* @return the image descriptor
*/
public static ImageDescriptor getImageDescriptor(String path) {
return AbstractUIPlugin.imageDescriptorFromPlugin("org.rssowl.ui", path); //$NON-NLS-1$
}
/**
* Log an Info Message.
*
* @param msg The message to log as Info.
*/
public void logInfo(@SuppressWarnings("unused")
String msg) {
// TODO Need a better logging facility here
// getLog().log(new Status(IStatus.INFO, getBundle().getSymbolicName(),
// IStatus.OK, msg, null));
}
/**
* Log an Error Message.
*
* @param msg The message to log as Error.
* @param e The occuring Exception to log.
*/
public void logError(String msg, Exception e) {
if (msg == null)
msg = ""; //$NON-NLS-1$
getLog().log(new Status(IStatus.ERROR, getBundle().getSymbolicName(), IStatus.ERROR, msg, e));
}
/**
* Create a IStatus out of the given message and exception.
*
* @param msg The message describing the error.
* @param e The Exception that occured.
* @return An IStatus out of the given message and exception.
*/
public IStatus createErrorStatus(String msg, Exception e) {
return new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), IStatus.ERROR, msg, e);
}
/**
* Create a IStatus out of the given message and exception.
*
* @param msg The message describing the info.
* @param e The Exception that occured.
* @return An IStatus out of the given message and exception.
*/
public IStatus createInfoStatus(String msg, Exception e) {
return new Status(IStatus.INFO, Activator.getDefault().getBundle().getSymbolicName(), IStatus.INFO, msg, e);
}
}