/** * Copyright (c) 2010 Marc A. Paradise This file is part of "BBSSH" BBSSH is based upon MidpSSH by Karl von Randow. * MidpSSH was based upon Telnet Floyd and FloydSSH by Radek Polak. 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., 675 Mass Ave, * Cambridge, MA 02139, USA. */ package org.bbssh; import net.rim.device.api.applicationcontrol.ApplicationPermissions; import net.rim.device.api.applicationcontrol.ApplicationPermissionsManager; import net.rim.device.api.io.FileNotFoundException; import net.rim.device.api.ui.UiApplication; import net.rim.device.api.ui.component.Dialog; import org.bbssh.model.ConnectionManager; import org.bbssh.model.DataStoreCleaner; import org.bbssh.model.KeyBindingManager; import org.bbssh.model.KeyManager; import org.bbssh.model.MacroManager; import org.bbssh.model.SettingsManager; import org.bbssh.notifications.NotificationManager; import org.bbssh.session.SessionManager; import org.bbssh.terminal.fonts.BBSSHFontManager; import org.bbssh.ui.screens.PrimaryScreen; import org.bbssh.ui.screens.RecoveryScreen; import org.bbssh.util.Logger; import org.bbssh.util.Tools; import org.bbssh.util.Version; /** * Main application class. Launches front screen, PrimaryScreen. * * @author marc */ public class BBSSHApp extends UiApplication { PrimaryScreen screen; boolean initComplete = false; protected Object initMutex = new Object();; private boolean permissionGranted = false; public boolean isInTouchCompatibilityMode() { return false; } public BBSSHApp() { } public PrimaryScreen getPrimaryScreen() { return screen; } protected boolean verifyMinimalPermissions() { ApplicationPermissionsManager mgr = ApplicationPermissionsManager.getInstance(); if (mgr.getPermission(ApplicationPermissions.PERMISSION_INTER_PROCESS_COMMUNICATION) == ApplicationPermissions.VALUE_DENY) { ApplicationPermissions perm = new ApplicationPermissions(); perm.addPermission(ApplicationPermissions.PERMISSION_INTER_PROCESS_COMMUNICATION); // Note that in some versions of BBOS, this will ALWAYS prompt even // if the permissions is already granted - that's why the check // above is required. return mgr.invokePermissionsRequest(perm); } return true; } public void attemptRecovery(int reasonRes) { Logger.error("BBSSHApp.attemptRecovery"); try { RecoveryScreen rec = new RecoveryScreen(reasonRes); pushScreen(rec); enterEventDispatcher(); } catch (Throwable e) { Logger.error("BBSSHApp.attemptRecovery: exception reported " + e.getMessage() + " : " + e.toString()); } } void pushMainScreen() { Logger.info("Creating and pushing main screen onto display stack."); if (screen == null) { Class cl = PrimaryScreen.class; screen = (PrimaryScreen) Version.createOSObjectInstance(cl.getName()); } pushScreen(screen); } void immediateInitTasks() { // must do this FIRST - as the absence of data will cause subsequent // loadup/init // to automatically recreate their default data sets. DataStoreCleaner.cleanData(); // Since we're displaying connection list as the main screen, we need to // have // this initialization complete before we can do anything else. // @todo move this and the other background tasks to use bg, but block // startup // until compelted - this will allow cancelation of long load. ConnectionManager.getInstance().initialize(); // Force safe, non-threaded load of session manager. SessionManager.getInstance(); initComplete = true; } void deferInitTasks() { new Thread("Initial") { public void run() { synchronized (initMutex) { KeyBindingManager.getInstance().initialize(); MacroManager.getInstance().initialize(); KeyManager.getInstance().initialize(); try { BBSSHFontManager.initialize(); } catch (FileNotFoundException e) { Logger.error(e.getMessage()); } catch (IllegalStateException e) { Logger.error(e.getMessage()); } catch (Throwable e) { Logger.error(e.getMessage()); } } } }.start(); } public void deactivate() { if (!initComplete) return; super.deactivate(); SessionManager.getInstance().notifyAppDeactivate(); } public void activate() { if (!initComplete) return; super.activate(); SessionManager.getInstance().notifyAppActivate(); } public boolean requestPermissions(ApplicationPermissions perm) { ApplicationPermissionsManager mgr = ApplicationPermissionsManager.getInstance(); return mgr.invokePermissionsRequest(perm); } public Object getInitializationMutex() { return initMutex; } /** * Saves all user configurable options. */ public void saveAllSettings() { Logger.debug("Begin saveAllSettings."); try { ConnectionManager.getInstance().commitData(); } catch (Throwable t) { Logger.fatal("Connection save failed.", t); } try { MacroManager.getInstance().commitData(); } catch (Throwable t) { Logger.fatal("Macro save failed.", t); } try { KeyBindingManager.getInstance().commitData(); } catch (Throwable t) { Logger.fatal("Keybinding save failed.", t); } try { SettingsManager.getInstance().commitData(); } catch (Throwable t) { Logger.fatal("Settings save failed.", t); } Logger.debug("End saveAllSettings."); } /** * Checks if the requested permission exists. If it is set to "VALUE_DENY", prompts the user for that permission by * displaying the message provided. * * @param requiredPermType * PERMISSION_* constant * @param msg * message resource to display if permission is configured to 'deny' * @return true if permission is granted by the system or the user. */ public synchronized boolean requestPermission(final int requiredPermType, final int msg) { permissionGranted = false; invokeAndWait(new Runnable() { public void run() { if (ApplicationPermissionsManager.getInstance().getPermission(requiredPermType) == ApplicationPermissions.VALUE_DENY) { if (Dialog.ask(Dialog.D_YES_NO, Tools.getStringResource(msg)) == Dialog.YES) { ApplicationPermissions perm = new ApplicationPermissions(); perm.addPermission(requiredPermType); permissionGranted = requestPermissions(perm); } } else { permissionGranted = true; } } }); // Don't assemble the string if we're not logging this anyway. int level = permissionGranted ? Logger.LOG_LEVEL_INFO : Logger.LOG_LEVEL_ERROR; if (Logger.isLevelEnabled(level)) { Logger.log(level, "Permission requested: " + requiredPermType + " and result is : " + permissionGranted); } return permissionGranted; } /** * Convenience method to quickly get the BBSSHApp instance without casting. * * @return the single BBSSHApp instance */ public static BBSSHApp inst() { return ((BBSSHApp) UiApplication.getUiApplication()); } public void shutdownTasks() { SessionManager.getInstance().terminateAllSessions(); BBSSHApp.inst().saveAllSettings(); NotificationManager.inst().resetNotificationState(); NotificationManager.inst().terminateAllNotifications(); Logger.disableFileLogging(); BBSSHApp.inst().removeSystemListener(SessionManager.getInstance()); NotificationManager.inst().resetNotificationState(); } }