PageRenderTime 2689ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/rssowl-2.0.5/org.rssowl.ui/src/org/rssowl/ui/internal/Activator.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 509 lines | 289 code | 67 blank | 153 comment | 41 complexity | cc6e06dba08cf1d591c248ebebb9572a MD5 | raw file
  1. /* ********************************************************************** **
  2. ** Copyright notice **
  3. ** **
  4. ** (c) 2005-2009 RSSOwl Development Team **
  5. ** http://www.rssowl.org/ **
  6. ** **
  7. ** All rights reserved **
  8. ** **
  9. ** This program and the accompanying materials are made available under **
  10. ** the terms of the Eclipse Public License v1.0 which accompanies this **
  11. ** distribution, and is available at: **
  12. ** http://www.rssowl.org/legal/epl-v10.html **
  13. ** **
  14. ** A copy is found in the file epl-v10.html and important notices to the **
  15. ** license from the team is found in the textfile LICENSE.txt distributed **
  16. ** in this package. **
  17. ** **
  18. ** This copyright notice MUST APPEAR in all copies of the file! **
  19. ** **
  20. ** Contributors: **
  21. ** RSSOwl Development Team - initial API and implementation **
  22. ** **
  23. ** ********************************************************************** */
  24. package org.rssowl.ui.internal;
  25. import org.eclipse.core.runtime.CoreException;
  26. import org.eclipse.core.runtime.IProgressMonitor;
  27. import org.eclipse.core.runtime.ISafeRunnable;
  28. import org.eclipse.core.runtime.IStatus;
  29. import org.eclipse.core.runtime.Platform;
  30. import org.eclipse.core.runtime.SafeRunner;
  31. import org.eclipse.core.runtime.Status;
  32. import org.eclipse.jface.operation.IRunnableWithProgress;
  33. import org.eclipse.jface.resource.ImageDescriptor;
  34. import org.eclipse.swt.widgets.Display;
  35. import org.eclipse.ui.plugin.AbstractUIPlugin;
  36. import org.osgi.framework.BundleContext;
  37. import org.rssowl.core.Owl;
  38. import org.rssowl.core.util.CoreUtils;
  39. import org.rssowl.core.util.LoggingSafeRunnable;
  40. import org.rssowl.core.util.LongOperationMonitor;
  41. import org.rssowl.ui.internal.dialogs.StartupProgressDialog;
  42. import java.io.IOException;
  43. import java.io.OutputStreamWriter;
  44. import java.io.PrintWriter;
  45. import java.lang.reflect.InvocationTargetException;
  46. import java.net.BindException;
  47. import java.net.InetAddress;
  48. import java.net.MalformedURLException;
  49. import java.net.Socket;
  50. import java.net.URL;
  51. import java.net.UnknownHostException;
  52. import java.util.regex.Pattern;
  53. /**
  54. * The main plugin class to be used in the desktop.
  55. */
  56. public class Activator extends AbstractUIPlugin {
  57. /** ID of this Plugin */
  58. public static final String PLUGIN_ID = "org.rssowl.ui"; //$NON-NLS-1$
  59. /* The reg. expression for an URL */
  60. private static final String URL_REGEX = "(www([\\wv\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?)|(http|ftp|https|feed):\\/\\/[\\w]+(.[\\w]+)([\\wv\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?"; //$NON-NLS-1$
  61. /* The compiled pattern to match an URL */
  62. private static final Pattern URL_REGEX_PATTERN = Pattern.compile(URL_REGEX);
  63. /* Singleton Instance of this Plugin */
  64. private static Activator fgPlugin;
  65. private Thread fShutdownHook;
  66. private IStatus fStartupStatus = Status.OK_STATUS;
  67. private String fVersion;
  68. private String fNl;
  69. /**
  70. * The constructor.
  71. */
  72. public Activator() {
  73. fgPlugin = this;
  74. }
  75. /**
  76. * This method is called upon plug-in activation
  77. */
  78. @Override
  79. public void start(BundleContext context) throws Exception {
  80. super.start(context);
  81. fVersion = (String) fgPlugin.getBundle().getHeaders().get("Bundle-Version"); //$NON-NLS-1$
  82. fNl = System.getProperty("line.separator"); //$NON-NLS-1$
  83. if (fNl == null)
  84. fNl = "\n"; //$NON-NLS-1$
  85. /* Log Version Information */
  86. try {
  87. safeLogInfo("RSSOwl Starting Up (" + getUserAgent() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
  88. } catch (Exception e) {
  89. /* Something seriously went wrong using the Platform Log */
  90. }
  91. /*
  92. * Start internal Server (chance that System.exit() gets called!). It is cruicial
  93. * that no class from org.rssowl.core is loaded to avoid that a second instance
  94. * that is launching, starts up the core for a second time.
  95. */
  96. SafeRunner.run(new ISafeRunnable() {
  97. public void run() throws Exception {
  98. startServer();
  99. }
  100. public void handleException(Throwable e) {
  101. if (e instanceof CoreException)
  102. Activator.getDefault().getLog().log(((CoreException) e).getStatus());
  103. }
  104. });
  105. /* Register a Shutdown Hook */
  106. fShutdownHook = new Thread() {
  107. @Override
  108. public void run() {
  109. /* Shutdown UI */
  110. SafeRunner.run(new LoggingSafeRunnable() {
  111. public void run() throws Exception {
  112. if (Owl.isStarted() || Controller.isInitialized())
  113. Controller.getDefault().shutdown(true);
  114. }
  115. });
  116. /* Shutdown Core */
  117. SafeRunner.run(new LoggingSafeRunnable() {
  118. public void run() throws Exception {
  119. Owl.shutdown(true);
  120. }
  121. });
  122. /* Check for Log Message from Core */
  123. String logMessages = CoreUtils.getAndFlushLogMessages();
  124. if (logMessages != null && logMessages.length() > 0)
  125. safeLogError(logMessages, null);
  126. /* Log Shutdown Info */
  127. safeLogInfo("RSSOwl Shutting Down (emergency)" + fNl); //$NON-NLS-1$
  128. }
  129. };
  130. fShutdownHook.setPriority(Thread.MAX_PRIORITY);
  131. Runtime.getRuntime().addShutdownHook(fShutdownHook);
  132. /* Activate the Core Bundle */
  133. SafeRunner.run(new LoggingSafeRunnable() {
  134. public void run() throws Exception {
  135. startCore();
  136. }
  137. });
  138. /* Propagate startup to Controller */
  139. SafeRunner.run(new LoggingSafeRunnable() {
  140. public void run() throws Exception {
  141. /* Startup Controller */
  142. if (Owl.isStarted())
  143. Controller.getDefault().startup();
  144. }
  145. });
  146. /* Propagate post-ui startup to Controller (Eclipse Integration) */
  147. if (Application.IS_ECLIPSE) {
  148. SafeRunner.run(new LoggingSafeRunnable() {
  149. public void run() throws Exception {
  150. Display.getDefault().asyncExec(new Runnable() {
  151. public void run() {
  152. if (Owl.isStarted())
  153. Controller.getDefault().postWindowOpen();
  154. }
  155. });
  156. }
  157. });
  158. }
  159. }
  160. private void startCore() {
  161. /* Dialog to show progress */
  162. Display.setAppName("RSSOwl"); //$NON-NLS-1$
  163. Display.getDefault(); //Create the Display
  164. final StartupProgressDialog dialog = new StartupProgressDialog();
  165. dialog.setOpenOnRun(false);
  166. /* Runnable to start core */
  167. IRunnableWithProgress runnable = new IRunnableWithProgress() {
  168. public void run(IProgressMonitor monitor) {
  169. LongOperationMonitor callbackMonitor = new LongOperationMonitor(monitor) {
  170. private boolean updateUi = true;
  171. @Override
  172. public void beginLongOperation(boolean isCancelable) {
  173. if (!isLongOperationRunning()) {
  174. super.beginLongOperation(isCancelable);
  175. dialog.open();
  176. }
  177. }
  178. @Override
  179. public void worked(int work) {
  180. super.worked(work);
  181. if (updateUi)
  182. updateUi();
  183. }
  184. @Override
  185. public void subTask(String name) {
  186. super.subTask(name);
  187. if (updateUi)
  188. updateUi();
  189. }
  190. private void updateUi() {
  191. Display display = Display.getDefault();
  192. try {
  193. if (!isCanceled() && !display.isDisposed() && dialog.getShell() != null && !dialog.getShell().isDisposed()) {
  194. display.readAndDispatch();
  195. display.update();
  196. }
  197. }
  198. /*
  199. * Ensure to catch any Exception here and disable the update of the
  200. * UI given that the operation being performed can be a critical one.
  201. */
  202. catch (Exception e) {
  203. updateUi = false;
  204. logError(e.getMessage(), e);
  205. }
  206. }
  207. };
  208. /* Start Core */
  209. try {
  210. Owl.startup(callbackMonitor);
  211. }
  212. /* Handle OOM Error */
  213. catch (OutOfMemoryError e) {
  214. Activator.this.fStartupStatus = createErrorStatus(e.getMessage());
  215. Activator.getDefault().getLog().log(Activator.this.fStartupStatus);
  216. }
  217. /* Handle Exception (because any exception here is a show stopper) */
  218. catch (Exception e) {
  219. Activator.this.fStartupStatus = createErrorStatus(e.getMessage(), e);
  220. Activator.getDefault().getLog().log(Activator.this.fStartupStatus);
  221. }
  222. }
  223. };
  224. /* Execute the Runnable */
  225. try {
  226. dialog.run(false, true, runnable);
  227. } catch (InvocationTargetException e) {
  228. logError(e.getMessage(), e);
  229. } catch (InterruptedException e) {
  230. logError(e.getMessage(), e);
  231. }
  232. }
  233. IStatus getStartupStatus() {
  234. return fStartupStatus;
  235. }
  236. /* Start the Application Server */
  237. private void startServer() {
  238. ApplicationServer server = ApplicationServer.getDefault();
  239. try {
  240. server.startup();
  241. }
  242. /* Server alredady bound - perform hand-shake */
  243. catch (BindException e) {
  244. String link = parseLink(Platform.getCommandLineArgs());
  245. doHandshake(link);
  246. }
  247. /* Log any IOException */
  248. catch (IOException e) {
  249. logError(e.getMessage(), e);
  250. }
  251. }
  252. /* Return the first Link in this Array or NULL otherwise */
  253. private String parseLink(String[] commandLineArgs) {
  254. for (String arg : commandLineArgs) {
  255. if (looksLikeLink(arg))
  256. return arg;
  257. }
  258. return null;
  259. }
  260. /*
  261. * Return TRUE in case the given String looks like a Link.
  262. */
  263. private boolean looksLikeLink(String str) {
  264. /* Is empty or null? */
  265. if (!isSet(str))
  266. return false;
  267. /* Contains whitespaces ? */
  268. if (str.indexOf(' ') >= 0)
  269. return false;
  270. /* RegEx Link check */
  271. if (URL_REGEX_PATTERN.matcher(str).matches())
  272. return true;
  273. /* Try creating an URL object */
  274. try {
  275. new URL(str);
  276. } catch (MalformedURLException e) {
  277. return false;
  278. }
  279. /* String is an URL */
  280. return true;
  281. }
  282. /*
  283. * Returns TRUE in case the given String has a value that is not "" or <code>NULL</code>.
  284. */
  285. private boolean isSet(String str) {
  286. return (str != null && str.length() > 0);
  287. }
  288. /* Server already running. Pass a message to the running Server and exit. */
  289. private void doHandshake(String message) {
  290. try {
  291. Socket socket = new Socket(InetAddress.getByName(ApplicationServer.LOCALHOST), ApplicationServer.DEFAULT_SOCKET_PORT);
  292. PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
  293. writer.println(isSet(message) ? message : ApplicationServer.STARTUP_HANDSHAKE);
  294. writer.flush();
  295. /*
  296. * Send a message to the other running instance of RSSOwl and wait some
  297. * time, so that is has a chance to read the message. After that, the
  298. * other running instance will restore from taskbar or tray to show the
  299. * user. Then exit this instance consequently.
  300. */
  301. try {
  302. Thread.sleep(200);
  303. } catch (InterruptedException e) {
  304. System.exit(0);
  305. } finally {
  306. System.exit(0);
  307. }
  308. } catch (UnknownHostException e) {
  309. logError(Messages.Activator_ERROR_STARTUP, e);
  310. } catch (IOException e) {
  311. logError(Messages.Activator_ERROR_STARTUP, e);
  312. }
  313. }
  314. /**
  315. * This method is called when the plug-in is stopped
  316. */
  317. @Override
  318. public void stop(BundleContext context) throws Exception {
  319. /* Remove Shutdown Hook first that would run too otherwise */
  320. Runtime.getRuntime().removeShutdownHook(fShutdownHook);
  321. /* Propagate shutdown to Controller */
  322. SafeRunner.run(new LoggingSafeRunnable() {
  323. public void run() throws Exception {
  324. if (Owl.isStarted() || Controller.isInitialized())
  325. Controller.getDefault().shutdown(false);
  326. }
  327. });
  328. /* Proceed */
  329. super.stop(context);
  330. fgPlugin = null;
  331. }
  332. /**
  333. * Returns the shared instance.
  334. *
  335. * @return The shared instance.
  336. */
  337. public static Activator getDefault() {
  338. return fgPlugin;
  339. }
  340. /**
  341. * Returns an image descriptor for the image file at the given plug-in
  342. * relative path.
  343. *
  344. * @param path the path
  345. * @return the image descriptor
  346. */
  347. public static ImageDescriptor getImageDescriptor(String path) {
  348. return getImageDescriptor(PLUGIN_ID, path);
  349. }
  350. /**
  351. * Returns an image descriptor for the image file at the given plug-in
  352. * relative path.
  353. *
  354. * @param pluginId the ID of the plugin to load the image from.
  355. * @param path the path
  356. * @return the image descriptor
  357. */
  358. public static ImageDescriptor getImageDescriptor(String pluginId, String path) {
  359. return AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, path);
  360. }
  361. /**
  362. * Log an Info Message.
  363. *
  364. * @param msg The message to log as Info.
  365. */
  366. public static void safeLogInfo(String msg) {
  367. Activator activator = fgPlugin;
  368. if (activator != null)
  369. activator.getLog().log(new Status(IStatus.INFO, activator.getBundle().getSymbolicName(), IStatus.OK, msg, null));
  370. }
  371. /**
  372. * Log an Error Message.
  373. *
  374. * @param msg The message to log as Error.
  375. * @param e The occuring Exception to log.
  376. */
  377. public static void safeLogError(String msg, Throwable e) {
  378. if (fgPlugin != null)
  379. fgPlugin.logError(msg, e);
  380. }
  381. /**
  382. * Log an Error Message.
  383. *
  384. * @param msg The message to log as Error.
  385. * @param e The occuring Exception to log.
  386. */
  387. public void logError(String msg, Throwable e) {
  388. if (msg == null)
  389. msg = ""; //$NON-NLS-1$
  390. getLog().log(new Status(IStatus.ERROR, getBundle().getSymbolicName(), IStatus.ERROR, msg, e));
  391. }
  392. /**
  393. * Log a Warning Message.
  394. *
  395. * @param msg The message to log as Warning.
  396. * @param e The occuring Exception to log.
  397. */
  398. public void logWarning(String msg, Exception e) {
  399. if (msg == null)
  400. msg = ""; //$NON-NLS-1$
  401. getLog().log(new Status(IStatus.WARNING, getBundle().getSymbolicName(), IStatus.WARNING, msg, e));
  402. }
  403. /**
  404. * Create a IStatus out of the given message and exception.
  405. *
  406. * @param msg The message describing the error.
  407. * @param e The Exception that occured.
  408. * @return An IStatus out of the given message and exception.
  409. */
  410. public IStatus createErrorStatus(String msg, Exception e) {
  411. return new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), IStatus.ERROR, msg, e);
  412. }
  413. /**
  414. * Create a IStatus out of the given message.
  415. *
  416. * @param msg The message describing the error.
  417. * @return An IStatus out of the given message and exception.
  418. */
  419. public IStatus createErrorStatus(String msg) {
  420. return new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), msg);
  421. }
  422. /**
  423. * Create a IStatus out of the given message and exception.
  424. *
  425. * @param msg The message describing the info.
  426. * @param e The Exception that occured.
  427. * @return An IStatus out of the given message and exception.
  428. */
  429. public IStatus createInfoStatus(String msg, Exception e) {
  430. return new Status(IStatus.INFO, Activator.getDefault().getBundle().getSymbolicName(), IStatus.INFO, msg, e);
  431. }
  432. private String getUserAgent() {
  433. String os = Platform.getOS();
  434. if (Platform.OS_WIN32.equals(os))
  435. return "RSSOwl/" + fVersion + " (Windows; U; en)"; //$NON-NLS-1$ //$NON-NLS-2$
  436. else if (Platform.OS_LINUX.equals(os))
  437. return "RSSOwl/" + fVersion + " (X11; U; en)"; //$NON-NLS-1$//$NON-NLS-2$
  438. else if (Platform.OS_MACOSX.equals(os))
  439. return "RSSOwl/" + fVersion + " (Macintosh; U; en)"; //$NON-NLS-1$ //$NON-NLS-2$
  440. return "RSSOwl/" + fVersion; //$NON-NLS-1$
  441. }
  442. }