/* * ####################################################### * * Copyright (c) 2013, A. Weinberger. All rights reserved. * -------------------------------------------------------- */ package ale.controller; import it.sauronsoftware.junique.MessageHandler; import java.awt.Desktop; import java.awt.Frame; import java.io.FileInputStream; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; import java.security.InvalidParameterException; import java.util.List; import java.util.Locale; import java.util.PropertyResourceBundle; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.FileAppender; import org.apache.log4j.HTMLLayout; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; import ale.Constants; import ale.Constants.Error; import ale.model.Model; import ale.model.skin.Skin; import ale.model.skin.SkinPreviewVO; import ale.util.fileUtil.FileUtil; import ale.view.gui.chooser.QuickChooser; import ale.view.gui.dialogs.AboutDialog; import ale.view.gui.dialogs.AfterApplySkinDialog; import ale.view.gui.dialogs.ApplySkinDialog; import ale.view.gui.dialogs.DeleteSkinDialog; import ale.view.gui.dialogs.ErrorDialog; import ale.view.gui.dialogs.FirstStartDialog; import ale.view.gui.dialogs.NewSkinDialog; import ale.view.gui.dialogs.QuitConfirmDialog; import ale.view.gui.dialogs.RenameDialog; import ale.view.gui.dialogs.SaveAsDialog; import ale.view.gui.dialogs.SettingsDialog; import ale.view.gui.editor.Editor; import ale.view.gui.util.GUIStrings; /** * ------------------------------------------------- <br/> * Package: ale.controller <br/> * Class : Main <br/> * --------------------------- <br/> * <br/> * The <code>Main</code> class contains the control structur and is the head of the program flow. <br/> * Short info: All filename params whithout suffix. Change the suffix in the constants. * * See PROGRAM_PATH in Constants before testing. * <br/> * <br/> * Last edited: 25.04.2013 <br/> * ------------------------------------------------- <br/> */ public class Main { /** Latest Version */ public static final String VERSION = "1.03 beta"; /** Latest Build date */ public static final String LASTBUILD = "23.05.2013"; private static final URI WEBSITE = URI.create("http://www.art-of-axp.tk/"); private static Logger LOGGER = getLogger(); private static final String LOGGER_NAME = "all.class"; private static final String LOGGER_FILE = "log.html"; private static final Level LOG_LEVEL = Level.WARN; private static final String BACKUP_CMD = "backup"; private static Model model; private static ExecutorService exct; private static QuickChooser chooser; private static Editor editor; /** * Main. Start of the program. * * @param args Commands: backup */ public static void main(String[] args) { try { // Look and Feel UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { LOGGER.warn("Exception while trying to set the L&F!", e); } if (!SystemInformation.isWin7()) { showMessage("This program works only on Windows 7!", JOptionPane.ERROR_MESSAGE); return; } { // Unique Instance Block MessageHandler handler = new MessageHandler() { String ret = ""; @Override public String handle(String arg0) { try { if (editor != null) { editor.toFront(); editor.repaint(); editor.setExtendedState(Frame.NORMAL); } else if (chooser != null) { chooser.toFront(); chooser.repaint(); chooser.setExtendedState(Frame.NORMAL); } else { this.ret = null; executeThreads(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { ; } LOGGER.fatal("Deamon killed!"); SystemInformation.releaseJVMLock(); System.exit(1); } }); } } catch (Exception e) { ; } return this.ret; } }; if (SystemInformation.isAlreadyRunning(handler)) { if (SystemInformation.wakeUpOtherOne() != null) { return; } } } { // CMD Block if ((args != null) && (args.length > 0) && args[0].equals(BACKUP_CMD)) { System.out.println("Advanced Logon Editor Copyright (C) 2013 A. Weinberger"); System.out.println("This program comes with ABSOLUTELY NO WARRANTY!"); System.out.println("Please wait..."); Settings.loadProperties(Constants.SETTINGS_PATH); model = new Model(); Error err = model.initialize(); if (err == null) { if (Settings.backUpCreated()) { if (model.applyBackup()) { System.out.println("Backup applied!"); } else { System.out.println("Backup NOT applied! An error occured!"); } } else { System.out.println("No Backup available! First Use?\nWould you like to recreate the logonscreen? y/n"); try { String tmp = ""; byte buffer[] = new byte[10]; int i = System.in.read(buffer, 0, 10); tmp = new String(buffer, 0, i); if (tmp.trim().toLowerCase().equals("y")) { Skin newSkin = model.newSkin("backup", null, null, null); model.applySkin(newSkin); } } catch (IOException e) { System.out.println("Error: " + e); } } return; } System.out.println("An error occurred: " + err); } } // --> Settings.loadProperties(Constants.SETTINGS_PATH); updateLocale(Settings.getLocaleLanguage()); if (!Settings.skipFirstStartDialog()) { showFirstStartDialog(); } else { resume(); } } /** * The Firststartdialog calls this method after showing a message. */ public static void resume() { Settings.setSkipFirstStartDialog(true); Settings.saveProperties(Constants.SETTINGS_PATH); model = new Model(); Error err = model.initialize(); if (err == null) { showQuickChooser(); } else { handleUnhandableProblem(err + "", "Main.resume"); } } /** * Ends the program. * */ public static void shutdown() { Settings.saveProperties(Constants.SETTINGS_PATH); if (model != null) { model.shutdown(); model = null; } if (exct != null) { exct.shutdown(); exct = null; } if (chooser != null) { chooser.dispose(); chooser = null; } if (editor != null) { editor.dispose(); editor = null; } SystemInformation.releaseJVMLock(); } /* * ############################################################################## */ /** * Creates a new Quickchooser window. * */ public static void showQuickChooser() { if (editor != null) { editor.dispose(); editor = null; } chooser = new QuickChooser(); } /** * Creates a new Editor window. * * @param skinFilename The skin to load and show in the editor */ public static void showEditor(String skinFilename) { Path skinPath; if (!skinFilename.endsWith(Constants.SKINFILE_SUFFIX)) { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(skinFilename + Constants.SKINFILE_SUFFIX); } else { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(skinFilename); } if ((skinFilename != null) && !skinFilename.equals("") && FileUtil.control(skinPath) && (model != null)) { Skin skin = model.loadSkin(skinPath); if (skin != null) { if (editor != null) { editor.dispose(); editor = null; } if (chooser != null) { chooser.dispose(); chooser = null; } editor = new Editor(skin); } else { handleUnhandableProblem("Main.showEditor", "Skin load failed!"); } } else { throw new InvalidParameterException(); } } /** * Shows a the firststart dialog. * */ @SuppressWarnings("unused") public static void showFirstStartDialog() { new FirstStartDialog(); } /** * Shows a the newSkinDialog. * */ @SuppressWarnings("unused") public static void showNewSkinDialog() { new NewSkinDialog(); } /** * Shows the DeleteSkinDialog. * * @param filename skin to delete. */ @SuppressWarnings("unused") public static void showDeleteSkinDialog(String filename) { new DeleteSkinDialog(filename); } /** * Shows the showRenameSkinDialog. * * @param filename skin to rename. */ @SuppressWarnings("unused") public static void showRenameSkinDialog(String filename) { new RenameDialog(filename); } /** * Shows the apply skin dialog. * * @param filename skinfilename. */ @SuppressWarnings("unused") public static void showApplySkinDialog(String filename) { new ApplySkinDialog(filename); } /** * Shows a dialog with infos about the program. * */ @SuppressWarnings("unused") public static void showAboutDialog() { new AboutDialog(); } /** * Shows the settings menu. * */ @SuppressWarnings("unused") public static void showSettingsDialog() { new SettingsDialog(); } /** * Shows the save-as menu. * @param skin skin * */ @SuppressWarnings("unused") public static void showSaveAsDialog(Skin skin) { new SaveAsDialog(skin); } /** * Shows a dialog which asks if the user wants to continue without saving. * * @param skin skin, in order to save it * @param openNewSkin if the user switches from one skin to a new one. * @param openChooser if the user wants to open the chooser. */ @SuppressWarnings("unused") public static void showQuitConfirmationDialog(Skin skin, boolean openNewSkin, boolean openChooser) { new QuitConfirmDialog(skin, openChooser, openChooser); } /** * Opens the help docs. * */ public static void showHelpDocs() { if (FileUtil.control(Constants.PROGRAM_DOCS_PATH)) { try { Desktop.getDesktop().open(Constants.PROGRAM_DOCS_PATH.toFile()); } catch (IOException e) { LOGGER.error(e); } } } /** * Opens the homepage. * */ public static void showWebsite() { try { Desktop.getDesktop().browse(WEBSITE); } catch (IOException e) { LOGGER.error(e); } } /** * Opens a specific website. * * @param url url * @return boolean */ public static boolean showWebsite(String url) { boolean ret = false; if ((url != null) && !url.equals("")) { try { URI uri = new URI(url); Desktop.getDesktop().browse(uri); ret = true; } catch (IOException | URISyntaxException e) { LOGGER.error(e); } } return ret; } /* * ############################################################################## */ /** * Shows an editor window with a new skin * * @param strings name, author, website, image */ public static void newSkin(String... strings) { if (strings.length != 4) { throw new IllegalArgumentException(); } if ((strings != null) && (model != null)) { Skin newSkin = model.newSkin(strings[0], strings[1], strings[2], strings[3] == null ? null : Paths.get(strings[3])); if (newSkin != null) { editor = new Editor(newSkin); } else { showProblemMessage("Main.newSkin: Can not create new Skin!"); return; } if (chooser != null) { chooser.dispose(); } chooser = null; } else { throw new InvalidParameterException(); } } /** * Saves and shows the apply dialog. * * @param filename filename of the skin. */ @SuppressWarnings("unused") public static void applySkin(String filename) { Path skinPath; if (!filename.endsWith(Constants.SKINFILE_SUFFIX)) { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(filename + Constants.SKINFILE_SUFFIX); } else { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(filename); } if (model.applySkin(skinPath)) { new AfterApplySkinDialog(); } else { showProblemMessage("Main.applySkin: Skin was not applied!"); } } /** * Deletes a skin * * @param filename filename of the skin. */ public static void deleteSkin(String filename) { Path skinPath; if (!filename.endsWith(Constants.SKINFILE_SUFFIX)) { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(filename + Constants.SKINFILE_SUFFIX); } else { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(filename); } if (model.deleteSkin(skinPath)) { chooser.updateList(); } else { showProblemMessage("Main.deleteSkin: Skin was not deleted!"); } } /** * Saves a skin to the skin dir. * * @param skin skinobject */ public static void save(Skin skin) { if ((skin != null)) { if (!model.saveSkinToDefaultDirectory(skin)) { showProblemMessage("Main.save: Skin was not saved!"); } } else { throw new InvalidParameterException(); } } /** * Saves with new name. * * @param skin skin * @param newName new name */ public static void saveAs(Skin skin, String newName) { if ((skin != null) && (model != null) && (newName != null) && !newName.equals("")) { if (!model.saveAsSkinToDefaultDirectory(skin, newName)) { showProblemMessage("Main.saveAs: Skin was not saved!"); } } else { throw new InvalidParameterException(); } } /** * Renames a skin. ie saves with new name and deletes old. * * @param filename filename of the skin. * @param newName new name */ public static void renameSkin(String filename, String newName) { if ((newName != null) && !newName.equals("") && !filename.equals(newName)) { Path skinPath; if (!filename.endsWith(Constants.SKINFILE_SUFFIX)) { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(filename + Constants.SKINFILE_SUFFIX); } else { skinPath = Constants.PROGRAM_SKINS_PATH.resolve(filename); } saveAs(model.loadSkin(skinPath), newName); deleteSkin(filename); } } /** * Applies the backup * * @return boolean */ public static boolean applyBackup() { return model.applyBackup(); } /* * ############################################################################## */ /** * Updates the locale of the program. * * @param language language */ public static void updateLocale(Language language) { String l = Settings.getLocaleLanguage().getLanguageString(); String c = Settings.getLocaleLanguage().getCountryString(); Locale currentLocale = new Locale(l, c); PropertyResourceBundle localeRes = null; try (FileInputStream fis = new FileInputStream(Constants.PROGRAM_LOCALE_PATH.resolve( Constants.PROGRAM_I18N + "_" + currentLocale.getLanguage() + "_" + currentLocale.getCountry() + Constants.PROGRAM_I18N_SUFFIX).toFile())) { localeRes = new PropertyResourceBundle(fis); fis.close(); } catch (IOException e) { LOGGER.warn(e); } if (localeRes != null) { GUIStrings.initLocale(localeRes); if (chooser != null) { chooser.updateLocale(); chooser.repaint(); } if (editor != null) { editor.updateLocale(); editor.repaint(); } } else { handleUnhandableProblem("Error while reading locale file!", "updateLocale()"); } } /** * Returns the infos about the available skins. * * @return a list of preview objects. */ public static List<SkinPreviewVO> getAvailableSkins() { return model.getAvailableSkins(); } /* * ############################################################################## */ /** * * * @param err error string * @param where hint where it occured */ @SuppressWarnings("unused") public static void handleUnhandableProblem(String err, String where) { handleUnhandableProblem(); new ErrorDialog(err + "\n" + where); LOGGER.error(err + "-in-" + where); } /** * * * @param err exception */ @SuppressWarnings("unused") public static void handleUnhandableProblem(Throwable err) { handleUnhandableProblem(); if ((err.getStackTrace() != null) && (err.getStackTrace().length >= 2)) { new ErrorDialog(err.getMessage() + "\n" + err.getStackTrace()[0] + "\n" + err.getStackTrace()[1]); } else { new ErrorDialog(err.getMessage()); } LOGGER.error(err); for (StackTraceElement e : err.getStackTrace()) { LOGGER.error(e); } } private static void handleUnhandableProblem() { shutdown(); } /** * Shows a message dialog. * @param msg message * */ public static void showProblemMessage(String msg) { showMessage(msg, JOptionPane.WARNING_MESSAGE); LOGGER.error(msg); } private static void showMessage(String message, int icon) { JOptionPane.showMessageDialog(null, message, "", icon); } /* * ############################################################################## */ /** * Executes runnable objects. * * @param runnables runnables to execute */ public static void executeThreads(Runnable... runnables) { if (exct == null) { exct = Executors.newCachedThreadPool(); } for (Runnable r : runnables) { exct.execute(r); } } /** * * * @return the logger obj */ public static Logger getLogger() { if (LOGGER == null) { LOGGER = Logger.getLogger(LOGGER_NAME); final SimpleLayout layout = new SimpleLayout(); LOGGER.addAppender(new ConsoleAppender(layout)); final HTMLLayout layout2 = new HTMLLayout(); try { LOGGER.addAppender(new FileAppender(layout2, Constants.PROGRAM_PATH.resolve(LOGGER_FILE).toString(), true)); } catch (IOException e) { LOGGER.warn("Can't create FileAppender for " + Constants.PROGRAM_PATH.resolve(LOGGER_FILE).toFile().getAbsolutePath(), e); } } if (LOGGER != null) { LOGGER.setLevel(LOG_LEVEL); } return LOGGER; } }