/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2014 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.env.ui; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; import java.util.List; import javax.swing.Icon; import javax.swing.JFrame; import org.apache.commons.collections.CollectionUtils; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.openmicroscopy.shoola.env.Container; import org.openmicroscopy.shoola.env.data.model.AnalysisActivityParam; import org.openmicroscopy.shoola.env.data.model.ApplicationData; import org.openmicroscopy.shoola.env.data.model.DeleteActivityParam; import org.openmicroscopy.shoola.env.data.model.DownloadActivityParam; import org.openmicroscopy.shoola.env.data.model.DownloadAndLaunchActivityParam; import org.openmicroscopy.shoola.env.data.model.DownloadAndZipParam; import org.openmicroscopy.shoola.env.data.model.DownloadArchivedActivityParam; import org.openmicroscopy.shoola.env.data.model.ExportActivityParam; import org.openmicroscopy.shoola.env.data.model.FigureActivityParam; import org.openmicroscopy.shoola.env.data.model.MovieActivityParam; import org.openmicroscopy.shoola.env.data.model.OpenActivityParam; import org.openmicroscopy.shoola.env.data.model.ResultsObject; import org.openmicroscopy.shoola.env.data.model.SaveAsParam; import org.openmicroscopy.shoola.env.data.model.ScriptActivityParam; import org.openmicroscopy.shoola.env.data.model.TransferableActivityParam; import omero.gateway.SecurityContext; import omero.log.Logger; import org.openmicroscopy.shoola.util.file.ImportErrorObject; import org.openmicroscopy.shoola.util.ui.MessengerDialog; import org.openmicroscopy.shoola.util.ui.NotificationDialog; import org.openmicroscopy.shoola.util.ui.UIUtilities; import omero.gateway.model.ExperimenterData; /** * Implements the {@link UserNotifier} interface. * * @author Jean-Marie Burel      <a * href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Andrea Falconi      <a * href="mailto:a.falconi@dundee.ac.uk"> a.falconi@dundee.ac.uk</a> * @version 2.2 <small> (<b>Internal version:</b> $Revision$ $Date$) </small> * @since OME2.2 */ public class UserNotifierImpl implements UserNotifier, PropertyChangeListener { /** Default title for the error dialog. */ private static final String DEFAULT_ERROR_TITLE = "Error"; /** Default title for the warning dialog. */ private static final String DEFAULT_WARNING_TITLE = "Warning"; /** Default title for the info dialog. */ private static final String DEFAULT_INFO_TITLE = "Information"; /** * This is the common parent frame that we use to build every notification * dialog. We don't use the one already provided by <i>Swing</i> because we * need to set the <i>OME</i> icon in the title bar, so that notification * dialogs can inherit it. */ private static JFrame SHARED_FRAME = null; /** Reference to the manager. */ private UserNotifierManager manager; /** The dialog displaying the progress of the save. */ private ChangesDialog dialog; /** * Returns <code>true</code> if it is possible to write in the folder, * <code>false</code> otherwise. * * @param folder * The folder to handle. * @return See above. */ private boolean canWriteInFolder(File folder) { if (!folder.canWrite()) { notifyInfo("Download file", "The selected folder is write protected.\nPlease" + " select a different one."); return false; } return true; } /** * Utility method to print the error message * * @param e * The exception to handle. * @return See above. */ private String printErrorText(Throwable e) { if (e == null) return ""; StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); return sw.toString(); } /** * Brings up a notification dialog. * * @param title * The dialog title. * @param message * The dialog message. * @param icon * The icon to show by the message. */ private void showNotificationDialog(String title, String message, Icon icon) { NotificationDialog dialog = new NotificationDialog(SHARED_FRAME, title, message, icon); dialog.pack(); UIUtilities.centerAndShow(dialog); } /** * Returns the e-mail address of the user currently logged in, if no address * specified. * * @param email * The address to check. * @return See above. */ private String getEmail(String email) { if (email != null && email.trim().length() != 0) return email; ExperimenterData exp = manager.getExperimenter(); if (exp != null) email = exp.getEmail(); if (email == null) email = ""; return email; } /** * Brings up a messenger dialog. * * @param title * The dialog title. * @param summary * The dialog message. * @param detail * The detailed error message. * @param email * The e-mail address of the user. * @param toSubmit * The version of the software. */ private void showErrorDialog(String title, String summary, String detail, String email) { Exception e; if (detail == null) { if (summary == null) summary = ""; e = new Exception(summary); } else e = new Exception(detail); if (CommonsLangUtils.isEmpty(title)) title = DEFAULT_ERROR_TITLE; MessengerDialog d = new MessengerDialog(SHARED_FRAME, title, getEmail(email), e); d.setServerVersion(manager.getServerVersion()); d.addPropertyChangeListener(manager); d.setModal(true); UIUtilities.centerAndShow(d); } /** * Creates a new instance. * * @param c * Reference to the singleton {@link Container}. */ UserNotifierImpl(Container c) { manager = new UserNotifierManager(this, c); if (SHARED_FRAME == null) { SHARED_FRAME = new JFrame(); SHARED_FRAME.setIconImage(AbstractIconManager.getOMEImageIcon()); } } /** Displays the activity. */ void showActivity() { manager.showActivity(); } /** * Notifies that data are saved before closing or switching group. * * @param nodes * The nodes to handle. * @param listener * The listener to register. * @param ctx * The security context. * @return See above */ void notifySaving(List<Object> nodes, PropertyChangeListener listener, SecurityContext ctx) { dialog = new ChangesDialog(SHARED_FRAME, nodes, ctx); dialog.addPropertyChangeListener(this); if (listener != null) dialog.addPropertyChangeListener(listener); UIUtilities.centerAndShow(dialog); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyError(String, String) */ public void notifyError(String title, String summary) { if (CommonsLangUtils.isEmpty(title)) title = DEFAULT_ERROR_TITLE; showNotificationDialog(title, summary, IconManager.getDefaultErrorIcon()); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyError(String, String, Throwable) */ public void notifyError(String title, String summary, Throwable detail) { notifyError(title, summary, detail == null ? null : printErrorText(detail)); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyError(String, String, String, List, PropertyChangeListener) */ public void notifyError(String title, String summary, String email, List<ImportErrorObject> toSubmit, PropertyChangeListener listener) { if (CommonsLangUtils.isEmpty(title)) title = DEFAULT_ERROR_TITLE; if (email == null) email = ""; MessengerDialog d = new MessengerDialog(SHARED_FRAME, title, getEmail(email), toSubmit); d.setServerVersion(manager.getServerVersion()); d.addPropertyChangeListener(manager); if (listener != null) d.addPropertyChangeListener(listener); if (!CollectionUtils.isEmpty(toSubmit)) { d.setModal(false); d.setAlwaysOnTop(false); } UIUtilities.centerAndShow(d); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyError(String, String, String) */ public void notifyError(String title, String summary, String detail) { showErrorDialog(title, summary, detail, null); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyWarning(String, String) */ public void notifyWarning(String title, String message) { if (CommonsLangUtils.isEmpty(title)) title = DEFAULT_WARNING_TITLE; showNotificationDialog(title, message, IconManager.getDefaultWarnIcon()); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyWarning(String, String, String) */ public void notifyWarning(String title, String summary, String detail) { if (CommonsLangUtils.isEmpty(title)) title = DEFAULT_WARNING_TITLE; showErrorDialog(title, summary, detail, null); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyWarning(String, String, Throwable) */ public void notifyWarning(String title, String summary, Throwable detail) { notifyWarning(title, summary, detail == null ? null : detail.getMessage()); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyInfo(String, String) */ public void notifyInfo(String title, String message) { if (CommonsLangUtils.isEmpty(title)) title = DEFAULT_INFO_TITLE; showNotificationDialog(title, message, IconManager.getDefaultInfoIcon()); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyInfo(String, String, Icon) */ public void notifyInfo(String title, String message, Icon icon) { if (CommonsLangUtils.isEmpty(title)) title = DEFAULT_INFO_TITLE; if (icon == null) icon = IconManager.getDefaultInfoIcon(); showNotificationDialog(title, message, icon); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#submitMessage(String, String) */ public void submitMessage(String email, String comment) { MessengerDialog d = manager.getCommentDialog(SHARED_FRAME, getEmail(email)); d.setComment(comment); UIUtilities.centerAndShow(d); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#notifyActivity(SecurityContext, Object) */ public void notifyActivity(SecurityContext ctx, Object activity) { if (activity == null) return; ActivityComponent comp = null; boolean register = true; boolean uiRegister = true; boolean startActivity = true; if (activity instanceof MovieActivityParam) { MovieActivityParam p = (MovieActivityParam) activity; comp = new MovieActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof ExportActivityParam) { if (manager.hasRunningActivityOfType(ExportActivity.class)) { startActivity = false; } ExportActivityParam p = (ExportActivityParam) activity; comp = new ExportActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof DownloadAndLaunchActivityParam) { DownloadAndLaunchActivityParam p = (DownloadAndLaunchActivityParam) activity; comp = new DownloadAndLaunchActivity(this, manager.getRegistry(), ctx, p); uiRegister = p.isUIRegister(); } else if (activity instanceof DownloadActivityParam) { DownloadActivityParam p = (DownloadActivityParam) activity; File f = p.getFolder(); if (!f.isDirectory()) f = f.getParentFile(); if (!canWriteInFolder(f)) return; uiRegister = p.isUIRegister(); comp = new DownloadActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof FigureActivityParam) { FigureActivityParam p = (FigureActivityParam) activity; comp = new FigureActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof AnalysisActivityParam) { AnalysisActivityParam p = (AnalysisActivityParam) activity; comp = new AnalysisActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof ScriptActivityParam) { ScriptActivityParam p = (ScriptActivityParam) activity; comp = new ScriptActivity(this, manager.getRegistry(), ctx, p.getScript(), p.getIndex()); } else if (activity instanceof DownloadArchivedActivityParam) { DownloadArchivedActivityParam p = (DownloadArchivedActivityParam) activity; comp = new DownloadArchivedActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof DeleteActivityParam) { DeleteActivityParam p = (DeleteActivityParam) activity; comp = new DeleteActivity(this, manager.getRegistry(), p); uiRegister = p.isUIRegister(); } else if (activity instanceof OpenActivityParam) { OpenActivityParam p = (OpenActivityParam) activity; comp = new OpenObjectActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof DownloadAndZipParam) { DownloadAndZipParam p = (DownloadAndZipParam) activity; if (!canWriteInFolder(p.getFolder())) return; comp = new DownloadAndZipActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof SaveAsParam) { SaveAsParam p = (SaveAsParam) activity; File folder = p.getFolder(); if (folder != null) { if (folder.isFile() || !folder.exists()) folder = folder.getParentFile(); } if (!canWriteInFolder(folder)) return; comp = new SaveAsActivity(this, manager.getRegistry(), ctx, p); } else if (activity instanceof TransferableActivityParam) { TransferableActivityParam p = (TransferableActivityParam) activity; comp = new DataTransferActivity(this, manager.getRegistry(), p); } else if (activity instanceof ResultsObject) { ResultsObject p = (ResultsObject) activity; comp = new SaveResultsActivity(this, manager.getRegistry(), ctx, p); } if (comp != null) { if (startActivity) { if (register) comp.startActivity(); } manager.registerActivity(comp, uiRegister); if (startActivity) { manager.startActivity(false, comp); } } } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#hasRunningActivities() */ public boolean hasRunningActivities() { return manager.getRunningActivitiesCount() > 0; } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#clearActivities() */ public void clearActivities() { manager.clearActivities(); } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#openApplication(ApplicationData, String) */ public void openApplication(ApplicationData data, String path) { if (data == null && path == null) return; Logger logger = manager.getRegistry().getLogger(); try { String[] commandLineElements = ApplicationData.buildCommand(data, path == null ? null : new File(path)); logger.info(this, "Executing command & args: " + Arrays.toString(commandLineElements)); ProcessBuilder builder = new ProcessBuilder(commandLineElements); if (commandLineElements[0].matches(".*Preview\\.app.*")) { // workaround for OSX Preview.app; can't be called via full path // (will result in permissions exception) builder = new ProcessBuilder("open", "-a", "Preview", commandLineElements[1]); } builder.start(); } catch (Exception e) { logger.error(this, e.getMessage()); } } /** * Implemented as specified by {@link UserNotifier}. * * @see UserNotifier#setStatus(Object) */ public void setStatus(Object node) { if (dialog == null) return; dialog.setStatus(node); } /** * Listens to property fired by the <code>ChangesDialog</code> * * @see PropertyChangeListener#propertyChange(PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { String name = evt.getPropertyName(); if (ChangesDialog.DONE_PROPERTY.equals(name)) { if (dialog != null) { dialog.setVisible(false); dialog.dispose(); dialog = null; } } } }