001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.apps; 029 030import org.opencms.db.CmsUserSettings; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsResource; 033import org.opencms.file.CmsUser; 034import org.opencms.file.types.I_CmsResourceType; 035import org.opencms.json.JSONArray; 036import org.opencms.json.JSONException; 037import org.opencms.main.CmsException; 038import org.opencms.main.CmsLog; 039import org.opencms.main.OpenCms; 040import org.opencms.module.CmsModule; 041import org.opencms.module.CmsModuleManager; 042import org.opencms.ui.CmsUserIconHelper; 043import org.opencms.ui.I_CmsDialogContext; 044import org.opencms.ui.actions.CmsContextMenuActionItem; 045import org.opencms.ui.actions.I_CmsDefaultAction; 046import org.opencms.ui.apps.cacheadmin.CmsCacheAdminConfiguration; 047import org.opencms.ui.apps.cacheadmin.CmsCacheFolder; 048import org.opencms.ui.apps.cacheadmin.CmsCacheViewFlexConfiguration; 049import org.opencms.ui.apps.cacheadmin.CmsCacheViewImageConfiguration; 050import org.opencms.ui.apps.dbmanager.CmsDbExportConfiguration; 051import org.opencms.ui.apps.dbmanager.CmsDbImportHTTPConfiguration; 052import org.opencms.ui.apps.dbmanager.CmsDbImportServerConfiguration; 053import org.opencms.ui.apps.dbmanager.CmsDbManagerConfiguration; 054import org.opencms.ui.apps.dbmanager.CmsDbManagerFolder; 055import org.opencms.ui.apps.dbmanager.CmsDbPropertiesAppConfiguration; 056import org.opencms.ui.apps.dbmanager.CmsDbRemovePubLocksConfiguration; 057import org.opencms.ui.apps.dbmanager.CmsDbStaticExportConfiguration; 058import org.opencms.ui.apps.dbmanager.CmsDbSynchronizationConfiguration; 059import org.opencms.ui.apps.dbmanager.sqlconsole.CmsSqlConsoleAppConfiguration; 060import org.opencms.ui.apps.filehistory.CmsFileHistoryClearConfiguration; 061import org.opencms.ui.apps.filehistory.CmsFileHistoryConfiguration; 062import org.opencms.ui.apps.filehistory.CmsFileHistoryFolder; 063import org.opencms.ui.apps.git.CmsGitAppConfiguration; 064import org.opencms.ui.apps.linkvalidation.CmsLinkInFolderValidationConfiguration; 065import org.opencms.ui.apps.linkvalidation.CmsLinkValidationConfiguration; 066import org.opencms.ui.apps.linkvalidation.CmsLinkValidationExternalConfiguration; 067import org.opencms.ui.apps.linkvalidation.CmsLinkValidationFolder; 068import org.opencms.ui.apps.lists.CmsListManagerConfiguration; 069import org.opencms.ui.apps.logfile.CmsLogFileConfiguration; 070import org.opencms.ui.apps.modules.CmsModuleAppConfiguration; 071import org.opencms.ui.apps.projects.CmsProjectManagerConfiguration; 072import org.opencms.ui.apps.projects.CmsProjectOverviewConfiguration; 073import org.opencms.ui.apps.publishqueue.CmsPublishQueueConfiguration; 074import org.opencms.ui.apps.resourcetypes.CmsResourceTypeAppConfiguration; 075import org.opencms.ui.apps.scheduler.CmsScheduledJobsAppConfig; 076import org.opencms.ui.apps.search.CmsSourceSearchAppConfiguration; 077import org.opencms.ui.apps.searchindex.CmsSearchindexAppConfiguration; 078import org.opencms.ui.apps.sessions.CmsBroadCastConfigurtion; 079import org.opencms.ui.apps.shell.CmsShellAppConfiguration; 080import org.opencms.ui.apps.sitemanager.CmsSiteManagerConfiguration; 081import org.opencms.ui.apps.user.CmsAccountsAppConfiguration; 082import org.opencms.ui.contextmenu.CmsContextMenuItemProviderGroup; 083import org.opencms.ui.contextmenu.I_CmsContextMenuItem; 084import org.opencms.ui.contextmenu.I_CmsContextMenuItemProvider; 085import org.opencms.ui.editors.CmsAcaciaEditor; 086import org.opencms.ui.editors.CmsSourceEditor; 087import org.opencms.ui.editors.CmsXmlContentEditor; 088import org.opencms.ui.editors.CmsXmlPageEditor; 089import org.opencms.ui.editors.I_CmsEditor; 090import org.opencms.ui.editors.messagebundle.CmsMessageBundleEditor; 091import org.opencms.util.CmsStringUtil; 092import org.opencms.workplace.tools.CmsTool; 093import org.opencms.workplace.tools.CmsToolManager; 094import org.opencms.workplace.tools.I_CmsToolHandler; 095 096import java.io.File; 097import java.util.ArrayList; 098import java.util.Arrays; 099import java.util.Collection; 100import java.util.Collections; 101import java.util.Comparator; 102import java.util.HashMap; 103import java.util.HashSet; 104import java.util.Iterator; 105import java.util.LinkedHashSet; 106import java.util.List; 107import java.util.Map; 108import java.util.ServiceLoader; 109import java.util.Set; 110 111import org.apache.commons.logging.Log; 112 113import com.google.common.collect.ComparisonChain; 114import com.google.common.collect.Lists; 115import com.google.common.collect.Maps; 116import com.google.common.collect.Sets; 117 118/** 119 * The workplace app manager.<p> 120 */ 121public class CmsWorkplaceAppManager { 122 123 /** 124 * Comparator for configuration objects implementing I_CmsHasOrder.<p> 125 * 126 * @param <T> the type to compare 127 */ 128 public static class ConfigurationComparator<T extends I_CmsHasOrder> implements Comparator<T> { 129 130 /** 131 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 132 */ 133 public int compare(I_CmsHasOrder o1, I_CmsHasOrder o2) { 134 135 return ComparisonChain.start().compare(o1.getOrder(), o2.getOrder()).result(); 136 } 137 } 138 139 /** 140 * Wrapper for the navigation state.<p> 141 */ 142 public static class NavigationState { 143 144 /** The parameter separator. */ 145 public static final String PARAM_SEPARATOR = "/"; 146 147 /** The state parameters. */ 148 private String m_params = ""; 149 150 /** The view/app name. */ 151 private String m_viewName = ""; 152 153 /** 154 * Constructor.<p> 155 * 156 * @param stateString the state string to parse 157 */ 158 public NavigationState(String stateString) { 159 160 if (stateString.startsWith("!")) { 161 stateString = stateString.substring(1); 162 } 163 int separatorPos = stateString.indexOf(PARAM_SEPARATOR); 164 if (separatorPos > 0) { 165 m_viewName = stateString.substring(0, separatorPos); 166 m_params = stateString.substring(separatorPos + 1); 167 } else { 168 m_viewName = stateString; 169 } 170 if (m_viewName.endsWith("/")) { 171 m_viewName = m_viewName.substring(0, m_viewName.length() - 1); 172 } 173 } 174 175 /** 176 * Returns the parameter part of the state.<p> 177 * 178 * @return the parameters 179 */ 180 String getParams() { 181 182 return m_params; 183 } 184 185 /** 186 * Returns the view name.<p> 187 * 188 * @return the view name 189 */ 190 String getViewName() { 191 192 return m_viewName; 193 194 } 195 } 196 197 /** The administration category id. */ 198 public static final String ADMINISTRATION_CATEGORY_ID = "Administration"; 199 200 /** The legacy category id. */ 201 public static final String LEGACY_CATEGORY_ID = "Legacy"; 202 203 /** The main category id. */ 204 public static final String MAIN_CATEGORY_ID = "Main"; 205 206 /** The toolbar.css resource name. */ 207 public static final String TOOLBAR_CSS = "css/toolbar.css"; 208 209 /** The workplace app settings additional info key. */ 210 public static String WORKPLACE_APP_SETTINGS_KEY = "WORKPLACE_APP_SETTINGS"; 211 212 /** The workplace CSS module parameter name. */ 213 public static String WORKPLACE_CSS_PARAM = "workplace-css"; 214 215 /** The logger for this class. */ 216 protected static Log LOG = CmsLog.getLog(CmsWorkplaceAppManager.class.getName()); 217 218 /** The default quick launch apps, these can be overridden by the user. */ 219 private static final String[] DEFAULT_USER_APPS = new String[] { 220 CmsAccountsAppConfiguration.APP_ID, 221 CmsModuleAppConfiguration.APP_ID}; 222 223 /** The available editors. */ 224 private static final I_CmsEditor[] EDITORS = new I_CmsEditor[] { 225 new CmsAcaciaEditor(), 226 new CmsSourceEditor(), 227 new CmsXmlContentEditor(), 228 new CmsXmlPageEditor(), 229 new CmsMessageBundleEditor()}; 230 231 /** Legacy apps explicitly hidden from new workplace. */ 232 private static final Set<String> LEGACY_BLACKLIST = Sets.newConcurrentHashSet( 233 Arrays.asList( 234 "/accounts", 235 "/contenttools", 236 "/git", 237 "/scheduler", 238 "/galleryoverview", 239 "/projects", 240 "/project_overview", 241 "/history", 242 "/sites", 243 "/cache", 244 "/publishqueue", 245 "/database", 246 "/linkvalidation", 247 "/workplace", 248 "/modules", 249 "/searchindex")); 250 251 /** The additional info key for the user quick launch apps. */ 252 private static final String QUICK_LAUCH_APPS_KEY = "quick_launch_apps"; 253 254 /** The standard quick launch apps. */ 255 private static final String[] STANDARD_APPS = new String[] { 256 CmsPageEditorConfiguration.APP_ID, 257 CmsSitemapEditorConfiguration.APP_ID, 258 CmsFileExplorerConfiguration.APP_ID, 259 CmsAppHierarchyConfiguration.APP_ID}; 260 261 /** The additional style sheets. */ 262 private Collection<String> m_additionalStyleSheets; 263 264 /** The admin cms context. */ 265 private CmsObject m_adminCms; 266 267 /** The app categories. */ 268 private Map<String, I_CmsAppCategory> m_appCategories; 269 270 /** The configured apps. */ 271 private Map<String, I_CmsWorkplaceAppConfiguration> m_appsById = Maps.newHashMap(); 272 273 /** The user icon helper. */ 274 private CmsUserIconHelper m_iconHelper; 275 276 /** The standard quick launch apps. */ 277 private List<I_CmsWorkplaceAppConfiguration> m_standardQuickLaunchApps; 278 279 /** The additional workplace CSS URIs. */ 280 private Set<String> m_workplaceCssUris; 281 282 /** Menu item manager. */ 283 private CmsContextMenuItemProviderGroup m_workplaceMenuItemProvider; 284 285 /** 286 * Constructor.<p> 287 * 288 * @param adminCms the admin cms context 289 * 290 * @throws CmsException in case initializing the cms object fails 291 */ 292 public CmsWorkplaceAppManager(CmsObject adminCms) 293 throws CmsException { 294 295 m_adminCms = adminCms; 296 m_iconHelper = new CmsUserIconHelper(OpenCms.initCmsObject(m_adminCms)); 297 m_workplaceMenuItemProvider = new CmsContextMenuItemProviderGroup(); 298 m_workplaceMenuItemProvider.addProvider(CmsDefaultMenuItemProvider.class); 299 m_workplaceMenuItemProvider.initialize(); 300 } 301 302 /** 303 * Constructor for testing only.<p> 304 */ 305 protected CmsWorkplaceAppManager() { 306 // nothing to do 307 } 308 309 /** 310 * Returns the additional style sheets provided by I_CmsWorkplaceStylesheetProvider services.<p> 311 * 312 * @return the additional style sheets 313 */ 314 public Collection<String> getAdditionalStyleSheets() { 315 316 if (m_additionalStyleSheets == null) { 317 Set<String> stylesheets = new LinkedHashSet<>(); 318 for (I_CmsWorkplaceStylesheetProvider provider : ServiceLoader.load( 319 I_CmsWorkplaceStylesheetProvider.class)) { 320 stylesheets.addAll(provider.getStylesheets()); 321 } 322 m_additionalStyleSheets = Collections.unmodifiableSet(stylesheets); 323 } 324 return m_additionalStyleSheets; 325 } 326 327 /** 328 * Returns the app configuration with the given id.<p> 329 * 330 * @param appId the app id 331 * 332 * @return the app configuration 333 */ 334 public I_CmsWorkplaceAppConfiguration getAppConfiguration(String appId) { 335 336 return m_appsById.get(appId); 337 } 338 339 /** 340 * Returns the app configuration instances for the given ids.<p> 341 * 342 * @param appIds the app ids 343 * 344 * @return the app configurations 345 */ 346 public List<I_CmsWorkplaceAppConfiguration> getAppConfigurations(String... appIds) { 347 348 List<I_CmsWorkplaceAppConfiguration> result = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 349 for (int i = 0; i < appIds.length; i++) { 350 I_CmsWorkplaceAppConfiguration config = getAppConfiguration(appIds[i]); 351 if (config != null) { 352 result.add(config); 353 } 354 } 355 return result; 356 } 357 358 /** 359 * Returns the user app setting of the given type.<p> 360 * 361 * @param cms the cms context 362 * @param type the app setting type 363 * 364 * @return the app setting 365 * 366 * @throws InstantiationException in case instantiating the settings type fails 367 * @throws IllegalAccessException in case the settings default constructor is not accessible 368 */ 369 public <T extends I_CmsAppSettings> T getAppSettings(CmsObject cms, Class<T> type) 370 throws InstantiationException, IllegalAccessException { 371 372 CmsUser user = cms.getRequestContext().getCurrentUser(); 373 CmsUserSettings settings = new CmsUserSettings(user); 374 String settingsString = settings.getAdditionalPreference(type.getName(), true); 375 T result = type.newInstance(); 376 377 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(settingsString)) { 378 379 result.restoreSettings(settingsString); 380 381 } 382 383 return result; 384 } 385 386 /** 387 * Returns the configured categories.<p> 388 * 389 * @return the app categories 390 */ 391 public Collection<I_CmsAppCategory> getCategories() { 392 393 return Collections.unmodifiableCollection(m_appCategories.values()); 394 } 395 396 /** 397 * Returns the default action for the given context if available.<p> 398 * 399 * @param context the dialog context 400 * 401 * @return the default action 402 */ 403 public I_CmsDefaultAction getDefaultAction(I_CmsDialogContext context) { 404 405 return getDefaultAction(context, getMenuItemProvider()); 406 } 407 408 /** 409 * Returns the default action for the given context if available.<p> 410 * 411 * @param context the dialog context 412 * @param menuItemProvider the menu item provider 413 * 414 * @return the default action 415 */ 416 public I_CmsDefaultAction getDefaultAction( 417 I_CmsDialogContext context, 418 I_CmsContextMenuItemProvider menuItemProvider) { 419 420 I_CmsDefaultAction result = null; 421 int resultRank = -1; 422 if (context.getResources().size() == 1) { 423 for (I_CmsContextMenuItem menuItem : menuItemProvider.getMenuItems()) { 424 if ((menuItem instanceof CmsContextMenuActionItem) 425 && (((CmsContextMenuActionItem)menuItem).getWorkplaceAction() instanceof I_CmsDefaultAction)) { 426 I_CmsDefaultAction action = (I_CmsDefaultAction)((CmsContextMenuActionItem)menuItem).getWorkplaceAction(); 427 if (action.getVisibility(context).isActive()) { 428 if (result == null) { 429 result = action; 430 resultRank = action.getDefaultActionRank(context); 431 } else { 432 int rank = action.getDefaultActionRank(context); 433 if (rank > resultRank) { 434 result = action; 435 resultRank = rank; 436 } 437 } 438 } 439 } 440 } 441 } 442 return result; 443 } 444 445 /** 446 * Gets all configured quick launch apps, independent of the current user.<p> 447 * 448 * @return the quick launch apps 449 */ 450 public List<I_CmsWorkplaceAppConfiguration> getDefaultQuickLaunchConfigurations() { 451 452 if (m_standardQuickLaunchApps == null) { 453 454 m_standardQuickLaunchApps = Collections.unmodifiableList(getAppConfigurations(STANDARD_APPS)); 455 } 456 return m_standardQuickLaunchApps; 457 } 458 459 /** 460 * Returns the editor for the given resource.<p> 461 * 462 * @param resource the resource to edit 463 * @param plainText if plain text editing is required 464 * 465 * @return the editor 466 */ 467 public I_CmsEditor getEditorForResource(CmsResource resource, boolean plainText) { 468 469 List<I_CmsEditor> editors = new ArrayList<I_CmsEditor>(); 470 for (int i = 0; i < EDITORS.length; i++) { 471 if (EDITORS[i].matchesResource(resource, plainText)) { 472 editors.add(EDITORS[i]); 473 } 474 } 475 I_CmsEditor result = null; 476 if (editors.size() == 1) { 477 result = editors.get(0); 478 } else if (editors.size() > 1) { 479 Collections.sort(editors, new Comparator<I_CmsEditor>() { 480 481 public int compare(I_CmsEditor o1, I_CmsEditor o2) { 482 483 return o1.getPriority() > o2.getPriority() ? -1 : 1; 484 } 485 }); 486 result = editors.get(0); 487 } 488 return result; 489 } 490 491 /** 492 * Returns the editor for the given resource type.<p> 493 * 494 * @param type the resource type to edit 495 * @param plainText if plain text editing is required 496 * 497 * @return the editor 498 */ 499 public I_CmsEditor getEditorForType(I_CmsResourceType type, boolean plainText) { 500 501 List<I_CmsEditor> editors = new ArrayList<I_CmsEditor>(); 502 for (int i = 0; i < EDITORS.length; i++) { 503 if (EDITORS[i].matchesType(type, plainText)) { 504 editors.add(EDITORS[i]); 505 } 506 } 507 I_CmsEditor result = null; 508 if (editors.size() == 1) { 509 result = editors.get(0); 510 } else if (editors.size() > 1) { 511 Collections.sort(editors, new Comparator<I_CmsEditor>() { 512 513 public int compare(I_CmsEditor o1, I_CmsEditor o2) { 514 515 return o1.getPriority() > o2.getPriority() ? -1 : 1; 516 } 517 }); 518 result = editors.get(0); 519 } 520 return result; 521 } 522 523 /** 524 * Gets the menu item provider for the workplace.<p> 525 * 526 * @return the menu item provider 527 */ 528 public I_CmsContextMenuItemProvider getMenuItemProvider() { 529 530 return m_workplaceMenuItemProvider; 531 } 532 533 /** 534 * Gets the configured quick launch apps which are visible for the current user.<p> 535 * 536 * @param cms the current CMS context 537 * @return the list of available quick launch apps 538 */ 539 public List<I_CmsWorkplaceAppConfiguration> getQuickLaunchConfigurations(CmsObject cms) { 540 541 List<I_CmsWorkplaceAppConfiguration> result = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 542 result.addAll(getDefaultQuickLaunchConfigurations()); 543 result.addAll(getUserQuickLauchConfigurations(cms)); 544 Iterator<I_CmsWorkplaceAppConfiguration> it = result.iterator(); 545 while (it.hasNext()) { 546 I_CmsWorkplaceAppConfiguration appConfig = it.next(); 547 CmsAppVisibilityStatus visibility = appConfig.getVisibility(cms); 548 if (!visibility.isVisible()) { 549 it.remove(); 550 } 551 } 552 return result; 553 } 554 555 /** 556 * Returns the user icon helper.<p> 557 * 558 * @return the user icon helper 559 */ 560 public CmsUserIconHelper getUserIconHelper() { 561 562 return m_iconHelper; 563 } 564 565 /** 566 * Returns all available workplace apps.<p> 567 * 568 * @return the available workpllace apps 569 */ 570 public Collection<I_CmsWorkplaceAppConfiguration> getWorkplaceApps() { 571 572 return m_appsById.values(); 573 } 574 575 /** 576 * Returns the additional workplace CSS URIs.<p> 577 * 578 * @return the additional workplace CSS URIs 579 */ 580 public Collection<String> getWorkplaceCssUris() { 581 582 return m_workplaceCssUris; 583 } 584 585 /** 586 * Initializes the additional workplace CSS URIs.<p> 587 * They will be taken from the module parameter 'workplace-css' if present in any module.<p> 588 * 589 * @param moduleManager the module manager instance 590 */ 591 public void initWorkplaceCssUris(CmsModuleManager moduleManager) { 592 593 Set<String> cssUris = new HashSet<String>(); 594 for (CmsModule module : moduleManager.getAllInstalledModules()) { 595 String param = module.getParameter(WORKPLACE_CSS_PARAM); 596 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(param)) { 597 cssUris.add(param); 598 } 599 } 600 File cssFile = new File( 601 OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebApplication( 602 CmsStringUtil.joinPaths("resources", TOOLBAR_CSS))); 603 if (cssFile.exists()) { 604 cssUris.add(TOOLBAR_CSS); 605 } 606 m_workplaceCssUris = Collections.unmodifiableSet(cssUris); 607 } 608 609 /** 610 * Loads the workplace apps.<p> 611 */ 612 public void loadApps() { 613 614 m_appsById.clear(); 615 m_appCategories = loadCategories(); 616 addAppConfigurations(loadDefaultApps()); 617 addAppConfigurations(loadAppsUsingServiceLoader()); 618 addAppConfigurations(loadLegacyApps()); 619 } 620 621 /** 622 * Stores the given app setting within the users additional info.<p> 623 * 624 * @param cms the cms context 625 * @param type the app setting type, used as the settings key 626 * @param appSettings the settings to store 627 */ 628 public void storeAppSettings(CmsObject cms, Class<? extends I_CmsAppSettings> type, I_CmsAppSettings appSettings) { 629 630 CmsUser user = cms.getRequestContext().getCurrentUser(); 631 CmsUserSettings settings = new CmsUserSettings(user); 632 633 String currentSetting = settings.getAdditionalPreference(type.getName(), true); 634 String state = appSettings.getSettingsString(); 635 if (((state == null) && (currentSetting == null)) || ((state != null) && state.equals(currentSetting))) { 636 // nothing changed 637 return; 638 } 639 640 settings.setAdditionalPreference(type.getName(), state); 641 try { 642 settings.save(cms); 643 } catch (CmsException e) { 644 LOG.error("Failed to store workplace app settings for type " + type.getName(), e); 645 } 646 } 647 648 /** 649 * Returns the quick launch apps set for the current user.<p> 650 * 651 * @param cms the cms context 652 * 653 * @return the quick launch app configurations 654 */ 655 protected List<I_CmsWorkplaceAppConfiguration> getUserQuickLauchConfigurations(CmsObject cms) { 656 657 String apps_info = (String)cms.getRequestContext().getCurrentUser().getAdditionalInfo(QUICK_LAUCH_APPS_KEY); 658 String[] appIds = null; 659 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(apps_info)) { 660 try { 661 JSONArray ids = new JSONArray(apps_info); 662 appIds = new String[ids.length()]; 663 for (int i = 0; i < appIds.length; i++) { 664 appIds[i] = ids.getString(i); 665 } 666 } catch (JSONException e) { 667 LOG.error("Error parsing user quick launch apps setting.", e); 668 appIds = null; 669 } 670 } 671 return getAppConfigurations(appIds != null ? appIds : DEFAULT_USER_APPS); 672 } 673 674 /** 675 * Writes the user quick launch apps setting to the user additional info.<p> 676 * 677 * @param cms the cms context 678 * @param apps the app ids 679 * 680 * @throws Exception in case writing the user fails 681 */ 682 protected void setUserQuickLaunchApps(CmsObject cms, List<String> apps) throws Exception { 683 684 JSONArray appIds = new JSONArray(apps); 685 CmsUser user = cms.getRequestContext().getCurrentUser(); 686 String infoValue = appIds.toString(); 687 String previousApps = (String)user.getAdditionalInfo(QUICK_LAUCH_APPS_KEY); 688 // remove the additional info value to use default setting, in case the selected apps match the default apps 689 if (new JSONArray(DEFAULT_USER_APPS).toString().equals(infoValue)) { 690 infoValue = null; 691 } 692 // check if the additional info value needs to be changed 693 if ((infoValue == previousApps) || ((infoValue != null) && infoValue.equals(previousApps))) { 694 695 return; 696 } 697 if (infoValue == null) { 698 user.deleteAdditionalInfo(QUICK_LAUCH_APPS_KEY); 699 } else { 700 user.setAdditionalInfo(QUICK_LAUCH_APPS_KEY, infoValue); 701 } 702 cms.writeUser(user); 703 } 704 705 /** 706 * Adds the given app configuration.<p> 707 * 708 * @param appConfigs the app configuration 709 */ 710 private void addAppConfigurations(Collection<I_CmsWorkplaceAppConfiguration> appConfigs) { 711 712 for (I_CmsWorkplaceAppConfiguration appConfig : appConfigs) { 713 I_CmsWorkplaceAppConfiguration old = m_appsById.get(appConfig.getId()); 714 if ((old == null) || (old.getPriority() < appConfig.getPriority())) { 715 m_appsById.put(appConfig.getId(), appConfig); 716 } 717 } 718 } 719 720 /** 721 * Loads the App Folder.<p> 722 * 723 * @return list of all app folder 724 */ 725 private List<I_CmsFolderAppCategory> loadAppFolder() { 726 727 List<I_CmsFolderAppCategory> result = new ArrayList<I_CmsFolderAppCategory>(); 728 result.addAll( 729 Arrays.<I_CmsFolderAppCategory> asList( 730 new CmsLinkValidationFolder(), 731 new CmsFileHistoryFolder(), 732 new CmsDbManagerFolder(), 733 new CmsCacheFolder())); 734 return result; 735 } 736 737 /** 738 * Returns the configured apps using the service loader.<p> 739 * 740 * @return tthe configured apps 741 */ 742 private List<I_CmsWorkplaceAppConfiguration> loadAppsUsingServiceLoader() { 743 744 List<I_CmsWorkplaceAppConfiguration> appConfigurations = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 745 Iterator<I_CmsWorkplaceAppConfiguration> configs = ServiceLoader.load( 746 I_CmsWorkplaceAppConfiguration.class).iterator(); 747 while (configs.hasNext()) { 748 try { 749 I_CmsWorkplaceAppConfiguration config = configs.next(); 750 appConfigurations.add(config); 751 } catch (Throwable t) { 752 LOG.error("Error loading workplace app configuration from classpath.", t); 753 } 754 } 755 return appConfigurations; 756 } 757 758 /** 759 * Loads the app categories.<p> 760 * 761 * @return the app categories 762 */ 763 private Map<String, I_CmsAppCategory> loadCategories() { 764 765 Map<String, I_CmsAppCategory> appCategories = new HashMap<String, I_CmsAppCategory>(); 766 CmsAppCategory main = new CmsAppCategory(MAIN_CATEGORY_ID, null, 0, 0); 767 appCategories.put(main.getId(), main); 768 CmsAppCategory admin = new CmsAppCategory(ADMINISTRATION_CATEGORY_ID, null, 5, 0); 769 appCategories.put(admin.getId(), admin); 770 CmsAppCategory legacy = new CmsAppCategory(LEGACY_CATEGORY_ID, null, 10, 0); 771 appCategories.put(legacy.getId(), legacy); 772 List<I_CmsFolderAppCategory> folder = loadAppFolder(); 773 for (I_CmsFolderAppCategory appFolder : folder) { 774 appCategories.put(appFolder.getId(), appFolder); 775 } 776 Iterator<I_CmsAppCategory> categoryIt = ServiceLoader.load(I_CmsAppCategory.class).iterator(); 777 while (categoryIt.hasNext()) { 778 try { 779 I_CmsAppCategory cat = categoryIt.next(); 780 if (!appCategories.containsKey(cat.getId()) 781 || (appCategories.get(cat.getId()).getPriority() < cat.getPriority())) { 782 appCategories.put(cat.getId(), cat); 783 } 784 } catch (Throwable t) { 785 LOG.error("Error loading workplace app category from classpath.", t); 786 } 787 } 788 return appCategories; 789 } 790 791 /** 792 * Loads the default apps.<p> 793 * 794 * @return the default apps 795 */ 796 private Collection<I_CmsWorkplaceAppConfiguration> loadDefaultApps() { 797 798 List<I_CmsWorkplaceAppConfiguration> result = Lists.newArrayList(); 799 result.addAll( 800 Arrays.<I_CmsWorkplaceAppConfiguration> asList( 801 new CmsSitemapEditorConfiguration(), 802 new CmsPageEditorConfiguration(), 803 new CmsFileExplorerConfiguration(), 804 new CmsScheduledJobsAppConfig(), 805 new CmsAppHierarchyConfiguration(), 806 new CmsEditorConfiguration(), 807 new CmsQuickLaunchEditorConfiguration(), 808 new CmsProjectManagerConfiguration(), 809 new CmsProjectOverviewConfiguration(), 810 new CmsCacheAdminConfiguration(), 811 new CmsCacheViewFlexConfiguration(), 812 new CmsCacheViewImageConfiguration(), 813 new CmsFileHistoryConfiguration(), 814 new CmsFileHistoryClearConfiguration(), 815 new CmsLinkValidationConfiguration(), 816 new CmsLinkValidationExternalConfiguration(), 817 new CmsLinkInFolderValidationConfiguration(), 818 new CmsDbManagerConfiguration(), 819 new CmsDbImportHTTPConfiguration(), 820 new CmsDbImportServerConfiguration(), 821 new CmsDbExportConfiguration(), 822 new CmsDbStaticExportConfiguration(), 823 new CmsSqlConsoleAppConfiguration(), 824 new CmsDbRemovePubLocksConfiguration(), 825 new CmsDbSynchronizationConfiguration(), 826 new CmsDbPropertiesAppConfiguration(), 827 new CmsSearchindexAppConfiguration(), 828 new CmsLogFileConfiguration(), 829 new CmsSourceSearchAppConfiguration(), 830 new CmsListManagerConfiguration(), 831 new CmsSiteManagerConfiguration(), 832 new CmsPublishQueueConfiguration(), 833 new CmsGitAppConfiguration(), 834 new CmsBroadCastConfigurtion(), 835 new CmsModuleAppConfiguration(), 836 new CmsAccountsAppConfiguration(), 837 new CmsShellAppConfiguration(), 838 new CmsResourceTypeAppConfiguration())); 839 840 return result; 841 } 842 843 /** 844 * Loads the legacy apps.<p> 845 * 846 * @return the legacy apps 847 */ 848 private Collection<I_CmsWorkplaceAppConfiguration> loadLegacyApps() { 849 850 List<I_CmsWorkplaceAppConfiguration> configs = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 851 // avoid accessing the workplace manager during test case 852 if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_2_INITIALIZING) { 853 List<CmsTool> tools = OpenCms.getWorkplaceManager().getToolManager().getToolHandlers(); 854 for (CmsTool tool : tools) { 855 856 I_CmsToolHandler handler = tool.getHandler(); 857 String path = handler.getPath(); 858 859 // only collecting first path level tools 860 if ((path.length() > 1) && (path.indexOf(CmsToolManager.TOOLPATH_SEPARATOR, 1) < 0)) { 861 if (!LEGACY_BLACKLIST.contains(path)) { 862 configs.add(new CmsLegacyAppConfiguration(handler)); 863 } 864 } 865 866 } 867 } 868 return configs; 869 } 870 871}