All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.i18n.CmsVfsBundleManager Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

There is a newer version: 18.0
Show newest version
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (C) Alkacon Software (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.i18n;

import org.opencms.db.CmsPublishedResource;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.main.CmsEvent;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.I_CmsEventListener;
import org.opencms.main.OpenCms;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import org.apache.commons.logging.Log;

import com.google.common.collect.Lists;

/**
 * Manages message bundles loaded from the VFS.

*/ public class CmsVfsBundleManager implements I_CmsEventListener { /** * Data holder for a base name and locale of a message bundle.

*/ private class NameAndLocale { /** The locale. */ private Locale m_locale; /** The base name. */ private String m_name; /** * Creates a new instance.

* * @param name the base name * @param locale the locale */ public NameAndLocale(String name, Locale locale) { m_name = name; m_locale = locale; } /** * Gets the locale.

* * @return the locale */ public Locale getLocale() { return m_locale; } /** * Gets the base name.

* * @return the base name */ public String getName() { return m_name; } } /** Resource type name for plain-text properties files containing messages. */ public static final String TYPE_PROPERTIES_BUNDLE = "propertyvfsbundle"; /** Resource type name for XML contents containing messages. */ public static final String TYPE_XML_BUNDLE = "xmlvfsbundle"; /** The logger instance for this class. */ protected static final Log LOG = CmsLog.getLog(CmsVfsBundleManager.class); /** The set of bundle base names. */ private Set m_bundleBaseNames; /** The CMS context to use. */ private CmsObject m_cms; /** Indicated if a reload is already scheduled. */ private boolean m_reloadIsScheduled; /** Thread generation counter. */ private int m_threadCount; /** * Creates a new instance.

* * @param cms the CMS context to use */ public CmsVfsBundleManager(CmsObject cms) { m_cms = cms; m_bundleBaseNames = new HashSet(); CmsVfsResourceBundle.setCmsObject(cms); OpenCms.getEventManager().addCmsEventListener( this, new int[] {I_CmsEventListener.EVENT_PUBLISH_PROJECT, I_CmsEventListener.EVENT_CLEAR_CACHES}); // immediately load all bundles for the first time reload(true); } /** * Collects all locales possibly used in the system.

* * @return the collection of all locales */ private static Collection getAllLocales() { Set result = new HashSet(); result.addAll(OpenCms.getWorkplaceManager().getLocales()); result.addAll(OpenCms.getLocaleManager().getAvailableLocales()); return result; } /** * @see org.opencms.main.I_CmsEventListener#cmsEvent(org.opencms.main.CmsEvent) */ public void cmsEvent(CmsEvent event) { // wrap in try-catch so that errors don't affect other handlers try { handleEvent(event); } catch (Throwable t) { LOG.error(t.getLocalizedMessage(), t); } } /** * Indicates if a reload thread is currently scheduled. * * @return true if a reload is currently scheduled */ public boolean isReloadScheduled() { return m_reloadIsScheduled; } /** * Re-initializes the resource bundles.

* * @param isStartup true when this is called during startup */ public synchronized void reload(boolean isStartup) { if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_1_CORE_OBJECT) { List xmlBundles = Lists.newArrayList(); List propertyBundles = Lists.newArrayList(); try { int xmlType = OpenCms.getResourceManager().getResourceType(TYPE_XML_BUNDLE).getTypeId(); xmlBundles = m_cms.readResources("/", CmsResourceFilter.ALL.addRequireType(xmlType), true); } catch (Exception e) { logError(e, isStartup); } try { int propType = OpenCms.getResourceManager().getResourceType(TYPE_PROPERTIES_BUNDLE).getTypeId(); propertyBundles = m_cms.readResources("/", CmsResourceFilter.ALL.addRequireType(propType), true); } catch (Exception e) { logError(e, isStartup); } try { synchronized (CmsResourceBundleLoader.class) { // Although the methods of CmsResourceBundleLoader which manipulate the cache // are synchronized, we synchronize the whole block to avoid intermediate states // where bundles have been removed from the cache but not re-added again for (String baseName : m_bundleBaseNames) { CmsResourceBundleLoader.flushBundleCache(baseName, true); } m_bundleBaseNames.clear(); for (CmsResource xmlBundle : xmlBundles) { addXmlBundle(xmlBundle); } for (CmsResource propertyBundle : propertyBundles) { addPropertyBundle(propertyBundle); } if (OpenCms.getWorkplaceManager() != null) { OpenCms.getWorkplaceManager().flushMessageCache(); } } } catch (Exception e) { logError(e, isStartup); } } } /** * Sets the information if a reload thread is currently scheduled. * * @param reloadIsScheduled if true there is a reload currently scheduled */ public void setReloadScheduled(boolean reloadIsScheduled) { m_reloadIsScheduled = reloadIsScheduled; } /** * Shuts down the VFS bundle manager.

* * This will cause the internal reloading Thread not reload in case it is still running.

*/ public void shutDown() { // we don't want to listen to further events OpenCms.getEventManager().removeCmsEventListener(this); setReloadScheduled(false); if (CmsLog.INIT.isInfoEnabled()) { CmsLog.INIT.info( org.opencms.staticexport.Messages.get().getBundle().key( org.opencms.staticexport.Messages.INIT_SHUTDOWN_1, this.getClass().getName())); } } /** * Logs an exception that occurred.

* * @param e the exception to log * @param logToErrorChannel if true erros should be written to the error channel instead of the info channel */ protected void logError(Exception e, boolean logToErrorChannel) { if (logToErrorChannel) { LOG.error(e.getLocalizedMessage(), e); } else { LOG.info(e.getLocalizedMessage(), e); } // if an error was logged make sure that the flag to schedule a reload is reset setReloadScheduled(false); } /** * Internal method for adding a resource bundle to the internal cache.

* * @param baseName the base name of the resource bundle * @param locale the locale of the resource bundle * @param bundle the resource bundle to add */ private void addBundle(String baseName, Locale locale, I_CmsResourceBundle bundle) { CmsResourceBundleLoader.addBundleToCache(baseName, locale, bundle); } /** * Adds a resource bundle based on a properties file in the VFS.

* * @param bundleResource the properties file */ private void addPropertyBundle(CmsResource bundleResource) { NameAndLocale nameAndLocale = getNameAndLocale(bundleResource); Locale locale = nameAndLocale.getLocale(); String baseName = nameAndLocale.getName(); m_bundleBaseNames.add(baseName); LOG.info( String.format( "Adding property VFS bundle (path=%s, name=%s, locale=%s)", bundleResource.getRootPath(), baseName, "" + locale)); Locale paramLocale = locale != null ? locale : CmsLocaleManager.getDefaultLocale(); CmsVfsBundleParameters params = new CmsVfsBundleParameters( nameAndLocale.getName(), bundleResource.getRootPath(), paramLocale, locale == null, CmsVfsResourceBundle.TYPE_PROPERTIES); CmsVfsResourceBundle bundle = new CmsVfsResourceBundle(params); addBundle(baseName, locale, bundle); } /** * Adds an XML based message bundle.

* * @param xmlBundle the XML content containing the message bundle data */ private void addXmlBundle(CmsResource xmlBundle) { String name = xmlBundle.getName(); String path = xmlBundle.getRootPath(); m_bundleBaseNames.add(name); LOG.info(String.format("Adding property VFS bundle (path=%s, name=%s)", xmlBundle.getRootPath(), name)); for (Locale locale : getAllLocales()) { CmsVfsBundleParameters params = new CmsVfsBundleParameters( name, path, locale, false, CmsVfsResourceBundle.TYPE_XML); CmsVfsResourceBundle bundle = new CmsVfsResourceBundle(params); addBundle(name, locale, bundle); } } /** * Extracts the locale and base name from a resource's file name.

* * @param bundleRes the resource for which to get the base name and locale * @return a bean containing the base name and locale */ private NameAndLocale getNameAndLocale(CmsResource bundleRes) { String fileName = bundleRes.getName(); if (TYPE_PROPERTIES_BUNDLE.equals(OpenCms.getResourceManager().getResourceType(bundleRes).getTypeName())) { String localeSuffix = CmsStringUtil.getLocaleSuffixForName(fileName); if (localeSuffix == null) { return new NameAndLocale(fileName, null); } else { String base = fileName.substring( 0, fileName.lastIndexOf(localeSuffix) - (1 /* cut off trailing underscore, too*/)); Locale locale = CmsLocaleManager.getLocale(localeSuffix); return new NameAndLocale(base, locale); } } else { return new NameAndLocale(fileName, null); } } /** * This actually handles the event.

* * @param event the received event */ private void handleEvent(CmsEvent event) { switch (event.getType()) { case I_CmsEventListener.EVENT_PUBLISH_PROJECT: //System.out.print(getEventName(event.getType())); String publishIdStr = (String)event.getData().get(I_CmsEventListener.KEY_PUBLISHID); if (publishIdStr != null) { CmsUUID publishId = new CmsUUID(publishIdStr); try { List publishedResources = m_cms.readPublishedResources(publishId); if (publishedResources.isEmpty()) { scheduleReload(); } else { String[] typesToMatch = new String[] {TYPE_PROPERTIES_BUNDLE, TYPE_XML_BUNDLE}; boolean reload = false; for (CmsPublishedResource res : publishedResources) { for (String typeName : typesToMatch) { if (OpenCms.getResourceManager().matchResourceType(typeName, res.getType())) { reload = true; break; } } } if (reload) { scheduleReload(); } } } catch (CmsException e) { LOG.error(e.getLocalizedMessage(), e); } } break; case I_CmsEventListener.EVENT_CLEAR_CACHES: default: scheduleReload(); break; } } /** * Schedules a bundle reload.

*/ private void scheduleReload() { if (!isReloadScheduled() && (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_1_CORE_OBJECT)) { // only schedule a reload if the system is not going down already m_threadCount++; Thread thread = new Thread("Bundle reload Thread " + m_threadCount) { @Override public void run() { setReloadScheduled(true); try { Thread.sleep(1000); } catch (Exception e) { // ignore } if (isReloadScheduled()) { reload(false); } setReloadScheduled(false); } }; thread.start(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy