org.opencms.ui.apps.CmsWorkplaceAppManager Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (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.ui.apps;
import org.opencms.db.CmsUserSettings;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsUser;
import org.opencms.json.JSONArray;
import org.opencms.json.JSONException;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.ui.CmsUserIconHelper;
import org.opencms.ui.I_CmsDialogContext;
import org.opencms.ui.actions.CmsContextMenuActionItem;
import org.opencms.ui.actions.I_CmsDefaultAction;
import org.opencms.ui.apps.projects.CmsProjectManagerConfiguration;
import org.opencms.ui.apps.scheduler.CmsScheduledJobsAppConfig;
import org.opencms.ui.apps.search.CmsSourceSearchAppConfiguration;
import org.opencms.ui.contextmenu.CmsContextMenuItemProviderGroup;
import org.opencms.ui.contextmenu.I_CmsContextMenuItem;
import org.opencms.ui.contextmenu.I_CmsContextMenuItemProvider;
import org.opencms.ui.editors.CmsAcaciaEditor;
import org.opencms.ui.editors.CmsSourceEditor;
import org.opencms.ui.editors.CmsXmlContentEditor;
import org.opencms.ui.editors.CmsXmlPageEditor;
import org.opencms.ui.editors.I_CmsEditor;
import org.opencms.ui.editors.messagebundle.CmsMessageBundleEditor;
import org.opencms.util.CmsStringUtil;
import org.opencms.workplace.tools.CmsTool;
import org.opencms.workplace.tools.CmsToolManager;
import org.opencms.workplace.tools.I_CmsToolHandler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import org.apache.commons.logging.Log;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* The workplace app manager.
*/
public class CmsWorkplaceAppManager {
/**
* Wrapper for the navigation state.
*/
public static class NavigationState {
/** The parameter separator. */
public static final String PARAM_SEPARATOR = "/";
/** The state parameters. */
private String m_params = "";
/** The view/app name. */
private String m_viewName = "";
/**
* Constructor.
*
* @param stateString the state string to parse
*/
public NavigationState(String stateString) {
if (stateString.startsWith("!")) {
stateString = stateString.substring(1);
}
int separatorPos = stateString.indexOf(PARAM_SEPARATOR);
if (separatorPos > 0) {
m_viewName = stateString.substring(0, separatorPos);
m_params = stateString.substring(separatorPos + 1);
} else {
m_viewName = stateString;
}
if (m_viewName.endsWith("/")) {
m_viewName = m_viewName.substring(0, m_viewName.length() - 1);
}
}
/**
* Returns the parameter part of the state.
*
* @return the parameters
*/
String getParams() {
return m_params;
}
/**
* Returns the view name.
*
* @return the view name
*/
String getViewName() {
return m_viewName;
}
}
/** The workplace app settings additional info key. */
public static String WORKPLACE_APP_SETTINGS_KEY = "WORKPLACE_APP_SETTINGS";
/** The logger for this class. */
protected static Log LOG = CmsLog.getLog(CmsWorkplaceAppManager.class.getName());
/** The available editors. */
private static final I_CmsEditor[] EDITORS = new I_CmsEditor[] {
new CmsAcaciaEditor(),
new CmsSourceEditor(),
new CmsXmlContentEditor(),
new CmsXmlPageEditor(),
new CmsMessageBundleEditor()};
/** Legacy apps explicitly hidden from new workplace. */
private static final Set LEGACY_BLACKLIST = Sets.newConcurrentHashSet(
Arrays.asList("/git", "/scheduler", "/galleryoverview", "/projects"));
/** The standard quick launch apps. */
private static final String[] STANDARD_APPS = new String[] {
CmsPageEditorConfiguration.APP_ID,
CmsSitemapEditorConfiguration.APP_ID,
CmsFileExplorerConfiguration.APP_ID,
CmsAppHierarchyConfiguration.APP_ID};
/** The default quick launch apps, these can be overridden by the user. */
private static final String[] DEFAULT_USER_APPS = new String[] {"/accounts", "/modules"};
/** The additional info key for the user quick launch apps. */
private static final String QUICK_LAUCH_APPS_KEY = "quick_launch_apps";
/** The main category id. */
public static final String MAIN_CATEGORY_ID = "Main";
/** The legacy category id. */
public static final String LEGACY_CATEGORY_ID = "Legacy";
/** The admin cms context. */
private CmsObject m_adminCms;
/** The app categories. */
private Map m_appCategories;
/** The configured apps. */
private Map m_appsById = Maps.newHashMap();
/** The user icon helper. */
private CmsUserIconHelper m_iconHelper;
/** Menu item manager. */
private CmsContextMenuItemProviderGroup m_workplaceMenuItemProvider;
/** The standard quick launch apps. */
private List m_standardQuickLaunchApps;
/**
* Constructor.
*
* @param adminCms the admin cms context
*
* @throws CmsException in case initializing the cms object fails
*/
public CmsWorkplaceAppManager(CmsObject adminCms)
throws CmsException {
m_adminCms = adminCms;
m_iconHelper = new CmsUserIconHelper(OpenCms.initCmsObject(m_adminCms));
m_workplaceMenuItemProvider = new CmsContextMenuItemProviderGroup();
m_workplaceMenuItemProvider.addProvider(CmsDefaultMenuItemProvider.class);
m_workplaceMenuItemProvider.initialize();
}
/**
* Constructor for testing only.
*/
protected CmsWorkplaceAppManager() {}
/**
* Returns the app configuration with the given id.
*
* @param appId the app id
*
* @return the app configuration
*/
public I_CmsWorkplaceAppConfiguration getAppConfiguration(String appId) {
return m_appsById.get(appId);
}
/**
* Returns the app configuration instances for the given ids.
*
* @param appIds the app ids
*
* @return the app configurations
*/
public List getAppConfigurations(String... appIds) {
List result = new ArrayList();
for (int i = 0; i < appIds.length; i++) {
I_CmsWorkplaceAppConfiguration config = getAppConfiguration(appIds[i]);
if (config != null) {
result.add(config);
}
}
return result;
}
/**
* Returns the user app setting of the given type.
*
* @param cms the cms context
* @param type the app setting type
*
* @return the app setting
*
* @throws InstantiationException in case instantiating the settings type fails
* @throws IllegalAccessException in case the settings default constructor is not accessible
*/
public T getAppSettings(CmsObject cms, Class type)
throws InstantiationException, IllegalAccessException {
CmsUser user = cms.getRequestContext().getCurrentUser();
CmsUserSettings settings = new CmsUserSettings(user);
String settingsString = settings.getAdditionalPreference(type.getName(), true);
T result = type.newInstance();
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(settingsString)) {
result.restoreSettings(settingsString);
}
return result;
}
/**
* Returns the configured categories.
*
* @return the app categories
*/
public Collection getCategories() {
return Collections.unmodifiableCollection(m_appCategories.values());
}
/**
* Returns the default action for the given context if available.
*
* @param context the dialog context
*
* @return the default action
*/
public I_CmsDefaultAction getDefaultAction(I_CmsDialogContext context) {
I_CmsDefaultAction result = null;
int resultRank = -1;
if (context.getResources().size() == 1) {
for (I_CmsContextMenuItem menuItem : getMenuItemProvider().getMenuItems()) {
if ((menuItem instanceof CmsContextMenuActionItem)
&& (((CmsContextMenuActionItem)menuItem).getWorkplaceAction() instanceof I_CmsDefaultAction)) {
I_CmsDefaultAction action = (I_CmsDefaultAction)((CmsContextMenuActionItem)menuItem).getWorkplaceAction();
if (action.getVisibility(context).isActive()) {
if (result == null) {
result = action;
resultRank = action.getDefaultActionRank(context);
} else {
int rank = action.getDefaultActionRank(context);
if (rank > resultRank) {
result = action;
resultRank = rank;
}
}
}
}
}
}
return result;
}
/**
* Returns the editor for the given resource.
*
* @param resource the resource to edit
* @param plainText if plain text editing is required
*
* @return the editor
*/
public I_CmsEditor getEditorForResource(CmsResource resource, boolean plainText) {
List editors = new ArrayList();
for (int i = 0; i < EDITORS.length; i++) {
if (EDITORS[i].matchesResource(resource, plainText)) {
editors.add(EDITORS[i]);
}
}
I_CmsEditor result = null;
if (editors.size() == 1) {
result = editors.get(0);
} else if (editors.size() > 1) {
Collections.sort(editors, new Comparator() {
public int compare(I_CmsEditor o1, I_CmsEditor o2) {
return o1.getPriority() > o2.getPriority() ? -1 : 1;
}
});
result = editors.get(0);
}
return result;
}
/**
* Gets the menu item provider for the workplace.
*
* @return the menu item provider
*/
public I_CmsContextMenuItemProvider getMenuItemProvider() {
return m_workplaceMenuItemProvider;
}
/**
* Gets the configured quick launch apps which are visible for the current user.
*
* @param cms the current CMS context
* @return the list of available quick launch apps
*/
public List getQuickLaunchConfigurations(CmsObject cms) {
List result = new ArrayList();
result.addAll(getDefaultQuickLaunchConfigurations());
result.addAll(getUserQuickLauchConfigurations(cms));
Iterator it = result.iterator();
while (it.hasNext()) {
I_CmsWorkplaceAppConfiguration appConfig = it.next();
CmsAppVisibilityStatus visibility = appConfig.getVisibility(cms);
if (!visibility.isVisible()) {
it.remove();
}
}
return result;
}
/**
* Returns the user icon helper.
*
* @return the user icon helper
*/
public CmsUserIconHelper getUserIconHelper() {
return m_iconHelper;
}
/**
* Returns all available workplace apps.
*
* @return the available workpllace apps
*/
public Collection getWorkplaceApps() {
return m_appsById.values();
}
/**
* Loads the workplace apps.
*/
public void loadApps() {
m_appsById.clear();
m_appCategories = loadCategories();
addAppConfigurations(loadDefaultApps());
addAppConfigurations(loadAppsUsingServiceLoader());
addAppConfigurations(loadLegacyApps());
}
/**
* Stores the given app setting within the users additional info.
*
* @param cms the cms context
* @param type the app setting type, used as the settings key
* @param appSettings the settings to store
*/
public void storeAppSettings(CmsObject cms, Class extends I_CmsAppSettings> type, I_CmsAppSettings appSettings) {
CmsUser user = cms.getRequestContext().getCurrentUser();
CmsUserSettings settings = new CmsUserSettings(user);
String currentSetting = settings.getAdditionalPreference(type.getName(), true);
String state = appSettings.getSettingsString();
if (((state == null) && (currentSetting == null)) || ((state != null) && state.equals(currentSetting))) {
// nothing changed
return;
}
settings.setAdditionalPreference(type.getName(), state);
try {
settings.save(cms);
} catch (CmsException e) {
LOG.error("Failed to store workplace app settings for type " + type.getName(), e);
}
}
/**
* Gets all configured quick launch apps, independent of the current user.
*
* @return the quick launch apps
*/
protected List getDefaultQuickLaunchConfigurations() {
if (m_standardQuickLaunchApps == null) {
m_standardQuickLaunchApps = Collections.unmodifiableList(getAppConfigurations(STANDARD_APPS));
}
return m_standardQuickLaunchApps;
}
/**
* Returns the quick launch apps set for the current user.
*
* @param cms the cms context
*
* @return the quick launch app configurations
*/
protected List getUserQuickLauchConfigurations(CmsObject cms) {
String apps_info = (String)cms.getRequestContext().getCurrentUser().getAdditionalInfo(QUICK_LAUCH_APPS_KEY);
String[] appIds = null;
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(apps_info)) {
try {
JSONArray ids = new JSONArray(apps_info);
appIds = new String[ids.length()];
for (int i = 0; i < appIds.length; i++) {
appIds[i] = ids.getString(i);
}
} catch (JSONException e) {
LOG.error("Error parsing user quick launch apps setting.", e);
appIds = null;
}
}
return getAppConfigurations(appIds != null ? appIds : DEFAULT_USER_APPS);
}
/**
* Writes the user quick launch apps setting to the user additional info.
*
* @param cms the cms context
* @param apps the app ids
*
* @throws CmsException in case writing the user fails
*/
protected void setUserQuickLaunchApps(CmsObject cms, List apps) throws CmsException {
JSONArray appIds = new JSONArray(apps);
CmsUser user = cms.getRequestContext().getCurrentUser();
user.setAdditionalInfo(QUICK_LAUCH_APPS_KEY, appIds.toString());
cms.writeUser(user);
}
/**
* Adds the given app configuration.
*
* @param appConfigs the app configuration
*/
private void addAppConfigurations(Collection appConfigs) {
for (I_CmsWorkplaceAppConfiguration appConfig : appConfigs) {
I_CmsWorkplaceAppConfiguration old = m_appsById.get(appConfig.getId());
if ((old == null) || (old.getPriority() < appConfig.getPriority())) {
m_appsById.put(appConfig.getId(), appConfig);
}
}
}
/**
* Returns the configured apps using the service loader.
*
* @return tthe configured apps
*/
private List loadAppsUsingServiceLoader() {
List appConfigurations = new ArrayList();
Iterator configs = ServiceLoader.load(
I_CmsWorkplaceAppConfiguration.class).iterator();
while (configs.hasNext()) {
try {
I_CmsWorkplaceAppConfiguration config = configs.next();
appConfigurations.add(config);
} catch (Throwable t) {
LOG.error("Error loading workplace app configuration from classpath.", t);
}
}
return appConfigurations;
}
/**
* Loads the app categories.
*
* @return the app categories
*/
private Map loadCategories() {
Map appCategories = new HashMap();
CmsAppCategory main = new CmsAppCategory(MAIN_CATEGORY_ID, null, 0, 0);
appCategories.put(main.getId(), main);
CmsAppCategory legacy = new CmsAppCategory(LEGACY_CATEGORY_ID, null, 1, 0);
appCategories.put(legacy.getId(), legacy);
Iterator categoryIt = ServiceLoader.load(I_CmsAppCategory.class).iterator();
while (categoryIt.hasNext()) {
try {
I_CmsAppCategory cat = categoryIt.next();
if (!appCategories.containsKey(cat.getId())
|| (appCategories.get(cat.getId()).getPriority() < cat.getPriority())) {
appCategories.put(cat.getId(), cat);
}
} catch (Throwable t) {
LOG.error("Error loading workplace app category from classpath.", t);
}
}
return appCategories;
}
/**
* Loads the default apps.
*
* @return the default apps
*/
private Collection loadDefaultApps() {
List result = Lists.newArrayList();
result.addAll(
Arrays. asList(
new CmsSitemapEditorConfiguration(),
new CmsPageEditorConfiguration(),
new CmsFileExplorerConfiguration(),
new CmsScheduledJobsAppConfig(),
new CmsAppHierarchyConfiguration(),
new CmsEditorConfiguration(),
new CmsQuickLaunchEditorConfiguration(),
new CmsTraditionalWorkplaceConfiguration(),
new CmsProjectManagerConfiguration(),
new CmsSourceSearchAppConfiguration()));
return result;
}
/**
* Loads the legacy apps.
*
* @return the legacy apps
*/
private Collection loadLegacyApps() {
List configs = new ArrayList();
List tools = OpenCms.getWorkplaceManager().getToolManager().getToolHandlers();
for (CmsTool tool : tools) {
I_CmsToolHandler handler = tool.getHandler();
String path = handler.getPath();
// only collecting first path level tools
if ((path.length() > 1) && (path.indexOf(CmsToolManager.TOOLPATH_SEPARATOR, 1) < 0)) {
if (!LEGACY_BLACKLIST.contains(path)) {
configs.add(new CmsLegacyAppConfiguration(handler));
}
}
}
return configs;
}
}