de.decidr.ui.controller.VaadinTenantThemeInstaller.java Source code

Java tutorial

Introduction

Here is the source code for de.decidr.ui.controller.VaadinTenantThemeInstaller.java

Source

/*
 * The DecidR Development Team licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package de.decidr.ui.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import de.decidr.model.annotations.Reviewed;
import de.decidr.model.annotations.Reviewed.State;
import de.decidr.model.exceptions.TransactionException;
import de.decidr.model.facades.TenantFacade;
import de.decidr.model.logging.DefaultLogger;
import de.decidr.ui.main.DecidrUI;
import de.decidr.ui.main.ModelFacades;
import de.decidr.ui.main.UIConventions;
import de.decidr.ui.view.windows.TransactionErrorDialogComponent;

/**
 * This class manages the tenant theme
 * 
 * @author AT
 */
@Reviewed(reviewers = { "unknown" }, lastRevision = "0", currentReviewState = State.NeedsReview)
public class VaadinTenantThemeInstaller {

    private static final Logger logger = DefaultLogger.getLogger(VaadinTenantThemeInstaller.class);

    /**
     * Applies the default DecidR theme to the current application.
     */
    public static void applyDefaultTheme() {
        DecidrUI.getCurrent().setTheme(UIConventions.DEFAULT_THEME_NAME);
    }

    /**
     * Applies the custom theme of the given tenant to the current application.
     * If necessary, the theme is installed locally, first. If the tenant has no
     * custom theme, the current theme remains unchanged.
     * 
     * @param tenantId
     *            ID of tenant whose theme should be applied
     */
    public static void applyToCurrentApplication(long tenantId) {

        if (!isThemeInstalledLocally(tenantId)) {
            try {
                installLocally(tenantId);
            } catch (Exception e) {
                // since we cannot install the theme, don't even try to set it.
                return;
            }
        }

        if (isThemeInstalledLocally(tenantId)) {
            /* apply theme */
            DecidrUI.getCurrent().setTheme(UIConventions.getThemeName(tenantId));
        } else {
            logger.error("Custom theme for tenant " + tenantId
                    + " seems to be missing even though installLocally succeeded.");
        }

    }

    /**
     * Installs the custom theme of the given tenant, if that tenant has a
     * custom theme. If a current or outdated version of the custom theme is
     * already installed, it will be overwritten.
     * 
     * @param tenantId
     * @return whether a custom theme was successfully installed. Also returns
     *         true if the custom theme was already installed and has been
     *         overwritten.
     */
    public static boolean installLocally(long tenantId) {
        TenantFacade tenantFacade = ModelFacades.getTenantFacade();
        InputStream cssContents = null;
        InputStream logoFileContents = null;

        /*
         * The custom theme is created by copying the default theme and
         * replacing the logo and css files
         */
        File template = null;
        File destination = null;
        /*
         * Target files to replace
         */
        File cssFile = UIConventions.getCssFile(tenantId);
        File logoFile = UIConventions.getLogoFile(tenantId);

        try {
            cssContents = tenantFacade.getCurrentColorScheme(tenantId);
            logoFileContents = tenantFacade.getLogo(tenantId);

            /*
             * Create a copy of the default theme.
             */
            template = UIConventions.getThemeDirectory(UIConventions.DEFAULT_THEME_NAME);
            destination = UIConventions.getThemeDirectory(UIConventions.getThemeName(tenantId));
            if (!template.equals(destination)) {
                FileUtils.copyDirectory(template, destination);
            }

            /*
             * Replace CSS and logo
             */
            replaceFile(cssFile, cssContents);
            replaceFile(logoFile, logoFileContents);
        } catch (IOException e) {
            logger.error("Cannot create custom tenant theme from template", e);
            try {
                /*
                 * Undo creation of new directory if possible
                 */
                if (destination != null && destination.isDirectory()) {
                    FileUtils.deleteDirectory(destination);
                }
            } catch (IOException undoException) {
                if (destination != null) {
                    logger.error("Cannot undo creation of destination directory. We have a file corpse: "
                            + destination.getAbsolutePath(), undoException);
                }
            }
            return false;
        } catch (TransactionException e) {
            DecidrUI.getCurrent().getMainWindow().addWindow(new TransactionErrorDialogComponent(e));
            return false;
        } finally {
            IOUtils.closeQuietly(cssContents);
            IOUtils.closeQuietly(logoFileContents);
        }

        return true;
    }

    /**
     * Checks whether there is a local copy of the custom theme for the given
     * tenant. This method does not check if the tenant has a custom theme at
     * all.
     * 
     * @param tenantId
     *            ID of the tenant
     * @return whether the custom theme is installed.
     */
    public static boolean isThemeInstalledLocally(long tenantId) {
        return UIConventions.getCssFile(tenantId).exists();
    }

    /**
     * Replaces a file with the given contents.
     * 
     * @param toReplace
     *            file to replace
     * @param contents
     *            new contents for file
     * @throws IOException
     *             if some I/O error occurs.
     */
    private static void replaceFile(File toReplace, InputStream contents) throws IOException {
        toReplace.delete();
        toReplace.createNewFile();
        FileOutputStream output = new FileOutputStream(toReplace);
        try {
            IOUtils.copy(contents, output);
        } finally {
            IOUtils.closeQuietly(output);
        }
    }

}