Package org.rssowl.ui.internal

Source Code of org.rssowl.ui.internal.Activator

/*   **********************************************************************  **
**   Copyright notice                                                       **
**                                                                          **
**   (c) 2005-2009 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.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.rssowl.core.Owl;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.LoggingSafeRunnable;
import org.rssowl.core.util.LongOperationMonitor;
import org.rssowl.ui.internal.dialogs.StartupProgressDialog;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.BindException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.regex.Pattern;

/**
* 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$

  /* The reg. expression for an URL */
  private static final String URL_REGEX = "(www([\\wv\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?)|(http|ftp|https|feed):\\/\\/[\\w]+(.[\\w]+)([\\wv\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?"; //$NON-NLS-1$

  /* The compiled pattern to match an URL */
  private static final Pattern URL_REGEX_PATTERN = Pattern.compile(URL_REGEX);

  /* Singleton Instance of this Plugin */
  private static Activator fgPlugin;

  private Thread fShutdownHook;
  private IStatus fStartupStatus = Status.OK_STATUS;
  private String fVersion;
  private String fNl;

  /**
   * 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);
    fVersion = (String) fgPlugin.getBundle().getHeaders().get("Bundle-Version"); //$NON-NLS-1$
    fNl = System.getProperty("line.separator"); //$NON-NLS-1$
    if (fNl == null)
      fNl = "\n"; //$NON-NLS-1$

    /* Log Version Information */
    try {
      safeLogInfo("RSSOwl Starting Up (" + getUserAgent() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
    } catch (Exception e) {
      /* Something seriously went wrong using the Platform Log */
    }

    /*
     * 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 {
            if (Owl.isStarted() || Controller.isInitialized())
              Controller.getDefault().shutdown(true);
          }
        });

        /* Shutdown Core */
        SafeRunner.run(new LoggingSafeRunnable() {
          public void run() throws Exception {
            Owl.shutdown(true);
          }
        });

        /* Check for Log Message from Core */
        String logMessages = CoreUtils.getAndFlushLogMessages();
        if (logMessages != null && logMessages.length() > 0)
          safeLogError(logMessages, null);

        /* Log Shutdown Info */
        safeLogInfo("RSSOwl Shutting Down (emergency)" + fNl); //$NON-NLS-1$
      }
    };
    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 {

        /* Startup Controller */
        if (Owl.isStarted())
          Controller.getDefault().startup();
      }
    });

    /* Propagate post-ui startup to Controller (Eclipse Integration) */
    if (Application.IS_ECLIPSE) {
      SafeRunner.run(new LoggingSafeRunnable() {
        public void run() throws Exception {
          Display.getDefault().asyncExec(new Runnable() {
            public void run() {
              if (Owl.isStarted())
                Controller.getDefault().postWindowOpen();
            }
          });
        }
      });
    }
  }

  private void startCore() {

    /* Dialog to show progress */
    Display.setAppName("RSSOwl"); //$NON-NLS-1$
    Display.getDefault(); //Create the Display
    final StartupProgressDialog dialog = new StartupProgressDialog();
    dialog.setOpenOnRun(false);

    /* Runnable to start core */
    IRunnableWithProgress runnable = new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor) {
        LongOperationMonitor callbackMonitor = new LongOperationMonitor(monitor) {
          private boolean updateUi = true;

          @Override
          public void beginLongOperation(boolean isCancelable) {
            if (!isLongOperationRunning()) {
              super.beginLongOperation(isCancelable);
              dialog.open();
            }
          }

          @Override
          public void worked(int work) {
            super.worked(work);
            if (updateUi)
              updateUi();
          }

          @Override
          public void subTask(String name) {
            super.subTask(name);
            if (updateUi)
              updateUi();
          }

          private void updateUi() {
            Display display = Display.getDefault();
            try {
              if (!isCanceled() && !display.isDisposed() && dialog.getShell() != null && !dialog.getShell().isDisposed()) {
                display.readAndDispatch();
                display.update();
              }
            }

            /*
             * Ensure to catch any Exception here and disable the update of the
             * UI given that the operation being performed can be a critical one.
             */
            catch (Exception e) {
              updateUi = false;
              logError(e.getMessage(), e);
            }
          }
        };

        /* Start Core */
        try {
          Owl.startup(callbackMonitor);
        }

        /* Handle OOM Error */
        catch (OutOfMemoryError e) {
          Activator.this.fStartupStatus = createErrorStatus(e.getMessage());
          Activator.getDefault().getLog().log(Activator.this.fStartupStatus);
        }

        /* Handle Exception (because any exception here is a show stopper) */
        catch (Exception e) {
          Activator.this.fStartupStatus = createErrorStatus(e.getMessage(), e);
          Activator.getDefault().getLog().log(Activator.this.fStartupStatus);
        }
      }
    };

    /* Execute the Runnable */
    try {
      dialog.run(false, true, runnable);
    } catch (InvocationTargetException e) {
      logError(e.getMessage(), e);
    } catch (InterruptedException e) {
      logError(e.getMessage(), e);
    }
  }

  IStatus getStartupStatus() {
    return fStartupStatus;
  }

  /* Start the Application Server */
  private void startServer() {
    ApplicationServer server = ApplicationServer.getDefault();
    try {
      server.startup();
    }

    /* Server alredady bound - perform hand-shake */
    catch (BindException e) {
      String link = parseLink(Platform.getCommandLineArgs());
      doHandshake(link);
    }

    /* Log any IOException */
    catch (IOException e) {
      logError(e.getMessage(), e);
    }
  }

  /* Return the first Link in this Array or NULL otherwise */
  private String parseLink(String[] commandLineArgs) {
    for (String arg : commandLineArgs) {
      if (looksLikeLink(arg))
        return arg;
    }

    return null;
  }

  /*
   * Return TRUE in case the given String looks like a Link.
   */
  private boolean looksLikeLink(String str) {

    /* Is empty or null? */
    if (!isSet(str))
      return false;

    /* Contains whitespaces ? */
    if (str.indexOf(' ') >= 0)
      return false;

    /* RegEx Link check */
    if (URL_REGEX_PATTERN.matcher(str).matches())
      return true;

    /* Try creating an URL object */
    try {
      new URL(str);
    } catch (MalformedURLException e) {
      return false;
    }

    /* String is an URL */
    return true;
  }

  /*
   * Returns TRUE in case the given String has a value that is not "" or <code>NULL</code>.
   */
  private boolean isSet(String str) {
    return (str != null && str.length() > 0);
  }

  /* Server already running. Pass a message to the running Server and exit. */
  private void doHandshake(String message) {
    try {
      Socket socket = new Socket(InetAddress.getByName(ApplicationServer.LOCALHOST), ApplicationServer.DEFAULT_SOCKET_PORT);
      PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
      writer.println(isSet(message) ? message : ApplicationServer.STARTUP_HANDSHAKE);
      writer.flush();

      /*
       * Send a message to the other running instance of RSSOwl and wait some
       * time, so that is has a chance to read the message. After that, the
       * other running instance will restore from taskbar or tray to show the
       * user. Then exit this instance consequently.
       */
      try {
        Thread.sleep(200);
      } catch (InterruptedException e) {
        System.exit(0);
      } finally {
        System.exit(0);
      }
    } catch (UnknownHostException e) {
      logError(Messages.Activator_ERROR_STARTUP, e);
    } catch (IOException e) {
      logError(Messages.Activator_ERROR_STARTUP, 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 {
        if (Owl.isStarted() || Controller.isInitialized())
          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 getImageDescriptor(PLUGIN_ID, path);
  }

  /**
   * Returns an image descriptor for the image file at the given plug-in
   * relative path.
   *
   * @param pluginId the ID of the plugin to load the image from.
   * @param path the path
   * @return the image descriptor
   */
  public static ImageDescriptor getImageDescriptor(String pluginId, String path) {
    return AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, path);
  }

  /**
   * Log an Info Message.
   *
   * @param msg The message to log as Info.
   */
  public static void safeLogInfo(String msg) {
    Activator activator = fgPlugin;
    if (activator != null)
      activator.getLog().log(new Status(IStatus.INFO, activator.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 static void safeLogError(String msg, Throwable e) {
    if (fgPlugin != null)
      fgPlugin.logError(msg, e);
  }

  /**
   * Log an Error Message.
   *
   * @param msg The message to log as Error.
   * @param e The occuring Exception to log.
   */
  public void logError(String msg, Throwable e) {
    if (msg == null)
      msg = ""; //$NON-NLS-1$

    getLog().log(new Status(IStatus.ERROR, getBundle().getSymbolicName(), IStatus.ERROR, msg, e));
  }

  /**
   * Log a Warning Message.
   *
   * @param msg The message to log as Warning.
   * @param e The occuring Exception to log.
   */
  public void logWarning(String msg, Exception e) {
    if (msg == null)
      msg = ""; //$NON-NLS-1$

    getLog().log(new Status(IStatus.WARNING, getBundle().getSymbolicName(), IStatus.WARNING, 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.
   *
   * @param msg The message describing the error.
   * @return An IStatus out of the given message and exception.
   */
  public IStatus createErrorStatus(String msg) {
    return new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), msg);
  }

  /**
   * 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);
  }

  private String getUserAgent() {
    String os = Platform.getOS();
    if (Platform.OS_WIN32.equals(os))
      return "RSSOwl/" + fVersion + " (Windows; U; en)"; //$NON-NLS-1$ //$NON-NLS-2$
    else if (Platform.OS_LINUX.equals(os))
      return "RSSOwl/" + fVersion + " (X11; U; en)"; //$NON-NLS-1$//$NON-NLS-2$
    else if (Platform.OS_MACOSX.equals(os))
      return "RSSOwl/" + fVersion + " (Macintosh; U; en)"; //$NON-NLS-1$ //$NON-NLS-2$
    return "RSSOwl/" + fVersion; //$NON-NLS-1$
  }
}
TOP

Related Classes of org.rssowl.ui.internal.Activator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.