Package org.apache.roller.weblogger.business.themes

Source Code of org.apache.roller.weblogger.business.themes.ThemeManagerImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  The ASF 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.  For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.roller.weblogger.business.themes;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.InitializationException;
import org.apache.roller.weblogger.business.MediaFileManager;
import org.apache.roller.weblogger.business.Weblogger;
import org.apache.roller.weblogger.business.WeblogManager;
import org.apache.roller.weblogger.config.WebloggerConfig;
import org.apache.roller.weblogger.pojos.MediaFileDirectory;
import org.apache.roller.weblogger.pojos.Theme;
import org.apache.roller.weblogger.pojos.ThemeResource;
import org.apache.roller.weblogger.pojos.ThemeTemplate;
import org.apache.roller.weblogger.pojos.WeblogTemplate;
import org.apache.roller.weblogger.pojos.WeblogTheme;
import org.apache.roller.weblogger.pojos.Weblog;
import org.apache.roller.weblogger.pojos.MediaFile;
import org.apache.roller.weblogger.util.RollerMessages;

/**
* Base implementation of a ThemeManager.
*
* This particular implementation reads theme data off the filesystem
* and assumes that those themes are not changable at runtime.
*/
@com.google.inject.Singleton
public class ThemeManagerImpl implements ThemeManager {

   static FileTypeMap map = null;
   static {
         // TODO: figure out why PNG is missing from Java MIME types
        map = FileTypeMap.getDefaultFileTypeMap();
        if (map instanceof MimetypesFileTypeMap) {
            try {
                ((MimetypesFileTypeMap)map).addMimeTypes("image/png png PNG");
            } catch (Exception ignored) {}
        }
    }

    private static Log log = LogFactory.getLog(ThemeManagerImpl.class);
    private final Weblogger roller;
    // directory where themes are kept
    private String themeDir = null;
    // the Map contains ... (theme id, Theme)
    private Map themes = null;

    @com.google.inject.Inject
    protected ThemeManagerImpl(Weblogger roller) {

        this.roller = roller;

        // get theme directory from config and verify it
        this.themeDir = WebloggerConfig.getProperty("themes.dir");
        if (themeDir == null || themeDir.trim().length() < 1) {
            throw new RuntimeException("couldn't get themes directory from config");
        } else {
            // chop off trailing slash if it exists
            if (themeDir.endsWith("/")) {
                themeDir = themeDir.substring(0, themeDir.length() - 1);
            }

            // make sure it exists and is readable
            File themeDirFile = new File(themeDir);
            if (!themeDirFile.exists()
                    || !themeDirFile.isDirectory()
                    || !themeDirFile.canRead()) {
                throw new RuntimeException("couldn't access theme dir [" + themeDir + "]");
            }
        }
    }

    public void initialize() throws InitializationException {

        log.debug("Initializing Theme Manager");

        if (themeDir != null) {
            // rather than be lazy we are going to load all themes from
            // the disk preemptively and cache them
            this.themes = loadAllThemesFromDisk();

            log.info("Loaded " + this.themes.size() + " themes from disk.");
        }
    }

    /**
     * @see org.apache.roller.weblogger.model.ThemeManager#getTheme(java.lang.String)
     */
    public SharedTheme getTheme(String id)
            throws ThemeNotFoundException, WebloggerException {

        // try to lookup theme from library
        SharedTheme theme = (SharedTheme) this.themes.get(id);

        // no theme?  throw exception.
        if (theme == null) {
            throw new ThemeNotFoundException("Couldn't find theme [" + id + "]");
        }

        return theme;
    }

    /**
     * @see org.apache.roller.weblogger.model.ThemeManager#getTheme(weblog)
     */
    public WeblogTheme getTheme(Weblog weblog) throws WebloggerException {

        if (weblog == null) {
            return null;
        }

        WeblogTheme weblogTheme = null;

        // if theme is custom or null then return a WeblogCustomTheme
        if (weblog.getEditorTheme() == null
                || WeblogTheme.CUSTOM.equals(weblog.getEditorTheme())) {
            weblogTheme = new WeblogCustomTheme(weblog);

            // otherwise we are returning a WeblogSharedTheme
        } else {
            ThemeManager themeMgr = roller.getThemeManager();
            SharedTheme staticTheme =
                    (SharedTheme) this.themes.get(weblog.getEditorTheme());
            if (staticTheme != null) {
                weblogTheme = new WeblogSharedTheme(weblog, staticTheme);
            } else {
                log.warn("Unable to lookup theme " + weblog.getEditorTheme());
            }
        }

        // TODO: if somehow the theme is still null should we provide some
        // kind of fallback option like a default theme?

        return weblogTheme;
    }

    /**
     * @see org.apache.roller.weblogger.model.ThemeManager#getEnabledThemesList()
     *
     * TODO: reimplement enabled vs. disabled logic once we support it
     */
    public List getEnabledThemesList() {

        List all_themes = new ArrayList(this.themes.values());

        // sort 'em ... default ordering for themes is by name
        Collections.sort(all_themes);

        return all_themes;
    }

    /**
     * @see org.apache.roller.weblogger.model.ThemeManager#importTheme(website, theme)
     */
    public void importTheme(Weblog website, SharedTheme theme)
            throws WebloggerException {

        log.debug("Importing theme [" + theme.getName() + "] to weblog [" + website.getName() + "]");

        WeblogManager wmgr = roller.getWeblogManager();
        MediaFileManager fileMgr = roller.getMediaFileManager();
       
        MediaFileDirectory root = fileMgr.getMediaFileRootDirectory(website);
        log.warn("Weblog " + website.getHandle() + " does not have a root MediaFile directory");

        Set importedActionTemplates = new HashSet();
        ThemeTemplate themeTemplate = null;
        ThemeTemplate stylesheetTemplate = theme.getStylesheet();
        Iterator iter = theme.getTemplates().iterator();
        while (iter.hasNext()) {
            themeTemplate = (ThemeTemplate) iter.next();

            WeblogTemplate template = null;

            // if template is an action, lookup by action
            if (themeTemplate.getAction() != null
                    && !themeTemplate.getAction().equals(WeblogTemplate.ACTION_CUSTOM)) {
                importedActionTemplates.add(themeTemplate.getAction());
                template = wmgr.getPageByAction(website, themeTemplate.getAction());

                // otherwise, lookup by name
            } else {
                template = wmgr.getPageByName(website, themeTemplate.getName());
            }

            // Weblog does not have this template, so create it.
            boolean newTmpl = false;
            if (template == null) {
                template = new WeblogTemplate();
                template.setWebsite(website);
                newTmpl = true;
            }

            // TODO: fix conflict situation
            // it's possible that someone has defined a theme template which
            // matches 2 existing templates, 1 by action, the other by name

            // update template attributes
            // NOTE: we don't want to copy the template data for an existing stylesheet
            if (newTmpl || !themeTemplate.equals(stylesheetTemplate)) {
                template.setAction(themeTemplate.getAction());
                template.setName(themeTemplate.getName());
                template.setDescription(themeTemplate.getDescription());
                template.setLink(themeTemplate.getLink());
                template.setContents(themeTemplate.getContents());
                template.setHidden(themeTemplate.isHidden());
                template.setNavbar(themeTemplate.isNavbar());
                template.setTemplateLanguage(themeTemplate.getTemplateLanguage());
                // NOTE: decorators are deprecated starting in 4.0
                template.setDecoratorName(null);
                template.setLastModified(new Date());

                // save it
                wmgr.savePage(template);
            }
        }

        // now, see if the weblog has left over action templates that
        // need to be deleted because they aren't in their new theme
        for (int i = 0; i < WeblogTemplate.ACTIONS.length; i++) {
            String action = WeblogTemplate.ACTIONS[i];

            // if we didn't import this action then see if it should be deleted
            if (!importedActionTemplates.contains(action)) {
                WeblogTemplate toDelete = wmgr.getPageByAction(website, action);
                if (toDelete != null) {
                    log.debug("Removing stale action template " + toDelete.getId());
                    wmgr.removePage(toDelete);
                }
            }
        }


        // always update this weblog's theme and customStylesheet, then save
        website.setEditorTheme(WeblogTheme.CUSTOM);
        if (theme.getStylesheet() != null) {
            website.setCustomStylesheetPath(theme.getStylesheet().getLink());
        }
        wmgr.saveWeblog(website);

        // now lets import all the theme resources
        List resources = theme.getResources();
        Iterator iterat = resources.iterator();
        ThemeResource resource = null;
        while (iterat.hasNext()) {
            resource = (ThemeResource) iterat.next();

            log.debug("Importing resource " + resource.getPath());

            if (resource.isDirectory()) {
                MediaFileDirectory mdir =
                    fileMgr.getMediaFileDirectoryByPath(website, resource.getPath());
                if (mdir == null) {
                    log.debug("    Creating directory: " + resource.getPath());
                    mdir = fileMgr.createMediaFileDirectory(
                      fileMgr.getMediaFileRootDirectory(website), resource.getPath());
                    roller.flush();
                } else {
                    log.debug("    No action: directory already exists");
                }

            } else {
                String resourcePath = resource.getPath();

                MediaFileDirectory mdir = null;
                String justName = null;
                String justPath = null;

                if (resourcePath.indexOf("/") == -1) {
                    mdir = fileMgr.getMediaFileRootDirectory(website);
                    justPath = "";
                    justName = resourcePath;
                   
                } else {
                    justPath = resourcePath.substring(0, resourcePath.lastIndexOf("/"));
                    if (!justPath.startsWith("/")) justPath = "/" + justPath;
                    justName = resourcePath.substring(resourcePath.lastIndexOf("/") + 1);
                    mdir = fileMgr.getMediaFileDirectoryByPath(website, justPath);
                    if (mdir == null) {
                        log.debug("    Creating directory: " + justPath);
                        mdir = fileMgr.createMediaFileDirectoryByPath(website, justPath);
                        roller.flush();
                    }
                }

                MediaFile oldmf = fileMgr.getMediaFileByOriginalPath(website, justPath + "/" + justName);
                if (oldmf != null) {
                    fileMgr.removeMediaFile(website, oldmf);
                }

                // save file without file-type, quota checks, etc.
                InputStream is = resource.getInputStream();
                MediaFile mf = new MediaFile();
                mf.setDirectory(mdir);
                mf.setWeblog(website);
                mf.setName(justName);
                mf.setOriginalPath(justPath + "/" + justName);
                mf.setContentType(map.getContentType(justName));
                mf.setInputStream(is);
                mf.setLength(resource.getLength());

                log.debug("    Saving file: " + justName);
                log.debug("    Saviving in directory = " + mf.getDirectory());
                RollerMessages errors = new RollerMessages();
                fileMgr.createMediaFile(website, mf, errors);
                try {
                    resource.getInputStream().close();
                } catch (IOException ex) {
                    errors.addError("error.closingStream");
                    log.debug("ERROR closing inputstream");
                }
                if (errors.getErrorCount() > 0) {
                    throw new WebloggerException(errors.toString());
                }
                roller.flush();
            }
        }
    }

    /**
     * This is a convenience method which loads all the theme data from
     * themes stored on the filesystem in the roller webapp /themes/ directory.
     */
    private Map loadAllThemesFromDisk() {

        Map themeMap = new HashMap();

        // first, get a list of the themes available
        File themesdir = new File(this.themeDir);
        FilenameFilter filter = new FilenameFilter() {

            public boolean accept(File dir, String name) {
                File file =
                        new File(dir.getAbsolutePath() + File.separator + name);
                return file.isDirectory() && !file.getName().startsWith(".");
            }
        };
        String[] themenames = themesdir.list(filter);

        if (themenames == null) {
            log.warn("No themes loaded!  Perhaps you specified the wrong "
                    + "location for your themes directory?");
        }

        // now go through each theme and load it into a Theme object
        for (int i = 0; i < themenames.length; i++) {
            try {
                Theme theme = new SharedThemeFromDir(this.themeDir + File.separator + themenames[i]);
                if (theme != null) {
                    themeMap.put(theme.getId(), theme);
                }
            } catch (Throwable unexpected) {
                // shouldn't happen, so let's learn why it did
                log.error("Problem reading theme " + themenames[i], unexpected);
            }
        }

        return themeMap;
    }

    /**
     * @see ThemeManager#reLoadThemeFromDisk(String)
     */
    public boolean reLoadThemeFromDisk(String reloadTheme) {

        boolean reloaded = false;

        try {

            Theme theme = new SharedThemeFromDir(this.themeDir + File.separator
                    + reloadTheme);

            if (theme != null) {

                Theme loadedTheme = (Theme) themes.get(theme.getId());

                if (loadedTheme != null
                        && theme.getLastModified().after(loadedTheme.getLastModified())) {
                    themes.remove(theme.getId());
                    themes.put(theme.getId(), theme);
                    reloaded = true;
                }

            }

        } catch (Throwable unexpected) {
            // shouldn't happen, so let's learn why it did
            log.error("Problem reloading theme " + reloadTheme, unexpected);
        }

        return reloaded;

    }
}
TOP

Related Classes of org.apache.roller.weblogger.business.themes.ThemeManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.