ModuleRegistry.java
/*
* Copyright (C) 2003-2010 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* 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, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.platform.common.module;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.gatein.common.i18n.LocalizedString;
import org.gatein.pc.api.PortletInvoker;
import org.gatein.pc.api.PortletInvokerException;
import org.gatein.pc.api.info.MetaInfo;
import org.picocontainer.Startable;
/**
* Main registry to store and manage eXo Platform modules. Modules can be
* registered and also activated.<br>
* Created by The eXo Platform SAS Author : eXoPlatform exo@exoplatform.com
* Jun 24, 2010
*/
public class ModuleRegistry implements Startable {
public static final String ALL_MODULES_PROFILE = "all";
private static final Log LOG = ExoLogger.getExoLogger(ModuleRegistry.class);
private Map<String, Boolean> isPortletActiveCache = new ConcurrentHashMap<String, Boolean>();
private boolean isPortletDisplayNamesImported = false;
/**
* modules indexed by name
*
* @see Module#getName()
*/
private Map<String, Module> modulesByName = new HashMap<String, Module>();
/**
* modules indexed by webapp name
*/
private Map<String, Set<Module>> modulesByWebapp = new HashMap<String, Set<Module>>();
/**
* modules indexed by portlet name
*/
private Map<String, Set<Module>> modulesByPortlet = new HashMap<String, Set<Module>>();
/**
* List of portlets that are managed by profile, and aren't considered in
* its webapp
*/
private List<String> portletsManagedByProfile;
/**
* modules indexed by portlet name
*/
private Map<String, LocalizedString> portletDisplayNames = new HashMap<String, LocalizedString>();
@SuppressWarnings("unchecked")
public ModuleRegistry(InitParams initParams) {
if (initParams.containsKey("portlets.managed.by.profile")) {
portletsManagedByProfile = initParams.getValuesParam("portlets.managed.by.profile").getValues();
} else {
portletsManagedByProfile = new ArrayList<String>();
}
Iterator<Module> iterator = initParams.getObjectParamValues(Module.class).iterator();
while (iterator.hasNext()) {
Module module = iterator.next();
if (LOG.isDebugEnabled()) {
LOG.debug(module.toString());
}
modulesByName.put(module.getName(), module);
}
}
/**
* Add a module by plugin injection
*/
public void addModule(ModulePlugin modulePlugin) {
if (modulePlugin != null && modulePlugin.getModule() != null) {
modulesByName.put(modulePlugin.getModule().getName(), modulePlugin.getModule());
}
}
@Override
public void start() {
// Compute Modules by webapp & by portletId (= webapp/portletName )
Collection<Module> modules = getAvailableModules();
for (Module module : modules) {
for (String webappName : module.getWebapps()) {
Set<Module> webappModules = modulesByWebapp.get(webappName);
if (webappModules == null) {
webappModules = new HashSet<Module>();
modulesByWebapp.put(webappName, webappModules);
}
webappModules.add(module);
}
}
for (Module module : modules) {
if (module.getPortlets() != null && !module.getPortlets().isEmpty()) {
for (String portletId : module.getPortlets()) {
if (!portletId.contains("/")) {
LOG.warn(portletId + " isn't a valid portlet ID, it have to be something like: {webappName}/{portletName}.");
continue;
}
Set<Module> portletModules = modulesByPortlet.get(portletId);
if (portletModules == null) {
portletModules = new HashSet<Module>();
modulesByPortlet.put(portletId, portletModules);
if (!portletsManagedByProfile.contains(portletId)) {
// Add related webapp modules to this portletId modules
String[] portletIdSplitted = portletId.split("/");
String webappName = portletIdSplitted[0];
Set<Module> webappModules = modulesByWebapp.get(webappName);
if (webappModules != null && !webappModules.isEmpty()) {
portletModules.addAll(webappModules);
}
}
}
portletModules.add(module);
}
}
}
}
public String getDisplayName(String portletName, Locale locale) {
String portletDisplayName = portletName;
if (portletDisplayNames.get(portletName) != null) {
portletDisplayName = portletDisplayNames.get(portletName).getValue(locale, true).getString();
} else if (!isPortletDisplayNamesImported) {
PortletInvoker portletInvoker = (PortletInvoker) PortalContainer.getComponent(PortletInvoker.class);
try {
Set<org.gatein.pc.api.Portlet> portlets = portletInvoker.getPortlets();
for (org.gatein.pc.api.Portlet portlet : portlets) {
portletDisplayNames.put(portlet.getInfo().getName(), portlet.getInfo().getMeta().getMetaValue(MetaInfo.DISPLAY_NAME));
}
isPortletDisplayNamesImported = true;
} catch (PortletInvokerException exception) {
LOG.error("Error occurred when trying to import portlets", exception);
}
if (portletDisplayNames.get(portletName) != null) {
portletDisplayName = portletDisplayNames.get(portletName).getValue(locale, true).getString();
}
}
return portletDisplayName;
}
/**
* @param webappName
* @return List of profiles/modules that activate a webapp
*/
public Set<String> getModulesForWebapp(String webappName) {
Set<String> profileNames = new HashSet<String>();
Set<Module> webappModules = modulesByWebapp.get(webappName);
if (webappModules != null && !webappModules.isEmpty()) {
for (Module module : webappModules) {
profileNames.add(module.getName());
}
}
profileNames.add(ALL_MODULES_PROFILE);
return profileNames;
}
/**
* @param portletId
* @return List of profiles/modules that activate a portlet
*/
public Set<String> getModulesForPortlet(String portletId) {
Set<String> profileNames = new HashSet<String>();
Set<Module> portletModules = modulesByPortlet.get(portletId);
if (portletModules == null || portletModules.isEmpty()) {
if (!portletsManagedByProfile.contains(portletId)) {
// Add related webapp modules to this portletId modules too
String[] portletIdSplitted = portletId.split("/");
String webappName = portletIdSplitted[0];
profileNames = getModulesForWebapp(webappName);
}
} else {
for (Module module : portletModules) {
profileNames.add(module.getName());
}
}
profileNames.add(ALL_MODULES_PROFILE);
return profileNames;
}
public boolean isPortletActive(String portletId) {
// Read from cache
Boolean isPortletActive = isPortletActiveCache.get(portletId);
if (isPortletActive != null) {
return isPortletActive;
}
// Read active profiles
Set<String> portletActiveProfiles = getModulesForPortlet(portletId);
if (portletActiveProfiles.size() == 1 && portletActiveProfiles.contains(ALL_MODULES_PROFILE)) {
isPortletActive = true;
} else {
Set<String> currentActiveProfiles = PortalContainer.getProfiles();
portletActiveProfiles.retainAll(currentActiveProfiles);
isPortletActive = !portletActiveProfiles.isEmpty();
}
isPortletActiveCache.put(portletId, isPortletActive);
return isPortletActive;
}
@Override
public void stop() {}
/**
* Get all available modules
*
* @return the list of all modules registered
* @see #registerModule(Module)
*/
private Collection<Module> getAvailableModules() {
return modulesByName.values();
}
}