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.CmsFileHistoryConfiguration; 061import org.opencms.ui.apps.git.CmsGitAppConfiguration; 062import org.opencms.ui.apps.linkvalidation.CmsLinkInFolderValidationConfiguration; 063import org.opencms.ui.apps.linkvalidation.CmsLinkValidationConfiguration; 064import org.opencms.ui.apps.linkvalidation.CmsLinkValidationExternalConfiguration; 065import org.opencms.ui.apps.linkvalidation.CmsLinkValidationFolder; 066import org.opencms.ui.apps.lists.CmsListManagerConfiguration; 067import org.opencms.ui.apps.logfile.CmsLogFileConfiguration; 068import org.opencms.ui.apps.modules.CmsModuleAppConfiguration; 069import org.opencms.ui.apps.projects.CmsProjectManagerConfiguration; 070import org.opencms.ui.apps.projects.CmsProjectOverviewConfiguration; 071import org.opencms.ui.apps.publishqueue.CmsPublishQueueConfiguration; 072import org.opencms.ui.apps.resourcetypes.CmsResourceTypeAppConfiguration; 073import org.opencms.ui.apps.scheduler.CmsScheduledJobsAppConfig; 074import org.opencms.ui.apps.search.CmsSourceSearchAppConfiguration; 075import org.opencms.ui.apps.searchindex.CmsSearchindexAppConfiguration; 076import org.opencms.ui.apps.sessions.CmsBroadCastConfigurtion; 077import org.opencms.ui.apps.shell.CmsShellAppConfiguration; 078import org.opencms.ui.apps.sitemanager.CmsSiteManagerConfiguration; 079import org.opencms.ui.apps.unusedcontentfinder.CmsUnusedContentFinderConfiguration; 080import org.opencms.ui.apps.user.CmsAccountsAppConfiguration; 081import org.opencms.ui.apps.userdata.CmsUserDataAppConfiguration; 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 307 // nothing to do 308 } 309 310 /** 311 * Returns the additional style sheets provided by I_CmsWorkplaceStylesheetProvider services.<p> 312 * 313 * @return the additional style sheets 314 */ 315 public Collection<String> getAdditionalStyleSheets() { 316 317 if (m_additionalStyleSheets == null) { 318 Set<String> stylesheets = new LinkedHashSet<>(); 319 for (I_CmsWorkplaceStylesheetProvider provider : ServiceLoader.load( 320 I_CmsWorkplaceStylesheetProvider.class)) { 321 stylesheets.addAll(provider.getStylesheets()); 322 } 323 m_additionalStyleSheets = Collections.unmodifiableSet(stylesheets); 324 } 325 return m_additionalStyleSheets; 326 } 327 328 /** 329 * Returns the app configuration with the given id.<p> 330 * 331 * @param appId the app id 332 * 333 * @return the app configuration 334 */ 335 public I_CmsWorkplaceAppConfiguration getAppConfiguration(String appId) { 336 337 return m_appsById.get(appId); 338 } 339 340 /** 341 * Returns the app configuration instances for the given ids.<p> 342 * 343 * @param appIds the app ids 344 * 345 * @return the app configurations 346 */ 347 public List<I_CmsWorkplaceAppConfiguration> getAppConfigurations(String... appIds) { 348 349 List<I_CmsWorkplaceAppConfiguration> result = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 350 for (int i = 0; i < appIds.length; i++) { 351 I_CmsWorkplaceAppConfiguration config = getAppConfiguration(appIds[i]); 352 if (config != null) { 353 result.add(config); 354 } 355 } 356 return result; 357 } 358 359 /** 360 * Returns the user app setting of the given type.<p> 361 * 362 * @param cms the cms context 363 * @param type the app setting type 364 * 365 * @return the app setting 366 * 367 * @throws InstantiationException in case instantiating the settings type fails 368 * @throws IllegalAccessException in case the settings default constructor is not accessible 369 */ 370 public <T extends I_CmsAppSettings> T getAppSettings(CmsObject cms, Class<T> type) 371 throws InstantiationException, IllegalAccessException { 372 373 CmsUser user = cms.getRequestContext().getCurrentUser(); 374 CmsUserSettings settings = new CmsUserSettings(user); 375 String settingsString = settings.getAdditionalPreference(type.getName(), true); 376 T result = type.newInstance(); 377 378 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(settingsString)) { 379 380 result.restoreSettings(settingsString); 381 382 } 383 384 return result; 385 } 386 387 /** 388 * Returns the configured categories.<p> 389 * 390 * @return the app categories 391 */ 392 public Collection<I_CmsAppCategory> getCategories() { 393 394 return Collections.unmodifiableCollection(m_appCategories.values()); 395 } 396 397 /** 398 * Returns the default action for the given context if available.<p> 399 * 400 * @param context the dialog context 401 * 402 * @return the default action 403 */ 404 public I_CmsDefaultAction getDefaultAction(I_CmsDialogContext context) { 405 406 return getDefaultAction(context, getMenuItemProvider()); 407 } 408 409 /** 410 * Returns the default action for the given context if available.<p> 411 * 412 * @param context the dialog context 413 * @param menuItemProvider the menu item provider 414 * 415 * @return the default action 416 */ 417 public I_CmsDefaultAction getDefaultAction( 418 I_CmsDialogContext context, 419 I_CmsContextMenuItemProvider menuItemProvider) { 420 421 I_CmsDefaultAction result = null; 422 int resultRank = -1; 423 if (context.getResources().size() == 1) { 424 for (I_CmsContextMenuItem menuItem : menuItemProvider.getMenuItems()) { 425 if ((menuItem instanceof CmsContextMenuActionItem) 426 && (((CmsContextMenuActionItem)menuItem).getWorkplaceAction() instanceof I_CmsDefaultAction)) { 427 I_CmsDefaultAction action = (I_CmsDefaultAction)((CmsContextMenuActionItem)menuItem).getWorkplaceAction(); 428 if (action.getVisibility(context).isActive()) { 429 if (result == null) { 430 result = action; 431 resultRank = action.getDefaultActionRank(context); 432 } else { 433 int rank = action.getDefaultActionRank(context); 434 if (rank > resultRank) { 435 result = action; 436 resultRank = rank; 437 } 438 } 439 } 440 } 441 } 442 } 443 return result; 444 } 445 446 /** 447 * Gets all configured quick launch apps, independent of the current user.<p> 448 * 449 * @return the quick launch apps 450 */ 451 public List<I_CmsWorkplaceAppConfiguration> getDefaultQuickLaunchConfigurations() { 452 453 if (m_standardQuickLaunchApps == null) { 454 455 m_standardQuickLaunchApps = Collections.unmodifiableList(getAppConfigurations(STANDARD_APPS)); 456 } 457 return m_standardQuickLaunchApps; 458 } 459 460 /** 461 * Returns the editor for the given resource.<p> 462 * 463 * @param cms the CMS context 464 * @param resource the resource to edit 465 * @param plainText if plain text editing is required 466 * 467 * @return the editor 468 */ 469 public I_CmsEditor getEditorForResource(CmsObject cms, CmsResource resource, boolean plainText) { 470 471 List<I_CmsEditor> editors = new ArrayList<I_CmsEditor>(); 472 for (int i = 0; i < EDITORS.length; i++) { 473 try { 474 if (EDITORS[i].matchesResource(cms, resource, plainText)) { 475 editors.add(EDITORS[i]); 476 } 477 } catch (Exception e) { 478 LOG.error(e.getLocalizedMessage(), e); 479 } 480 } 481 I_CmsEditor result = null; 482 if (editors.size() == 1) { 483 result = editors.get(0); 484 } else if (editors.size() > 1) { 485 Collections.sort(editors, new Comparator<I_CmsEditor>() { 486 487 public int compare(I_CmsEditor o1, I_CmsEditor o2) { 488 489 return o1.getPriority() > o2.getPriority() ? -1 : 1; 490 } 491 }); 492 result = editors.get(0); 493 } 494 return result; 495 } 496 497 /** 498 * Returns the editor for the given resource type.<p> 499 * 500 * @param type the resource type to edit 501 * @param plainText if plain text editing is required 502 * 503 * @return the editor 504 */ 505 public I_CmsEditor getEditorForType(I_CmsResourceType type, boolean plainText) { 506 507 List<I_CmsEditor> editors = new ArrayList<I_CmsEditor>(); 508 for (int i = 0; i < EDITORS.length; i++) { 509 if (EDITORS[i].matchesType(type, plainText)) { 510 editors.add(EDITORS[i]); 511 } 512 } 513 I_CmsEditor result = null; 514 if (editors.size() == 1) { 515 result = editors.get(0); 516 } else if (editors.size() > 1) { 517 Collections.sort(editors, new Comparator<I_CmsEditor>() { 518 519 public int compare(I_CmsEditor o1, I_CmsEditor o2) { 520 521 return o1.getPriority() > o2.getPriority() ? -1 : 1; 522 } 523 }); 524 result = editors.get(0); 525 } 526 return result; 527 } 528 529 /** 530 * Gets the menu item provider for the workplace.<p> 531 * 532 * @return the menu item provider 533 */ 534 public I_CmsContextMenuItemProvider getMenuItemProvider() { 535 536 return m_workplaceMenuItemProvider; 537 } 538 539 /** 540 * Gets the configured quick launch apps which are visible for the current user.<p> 541 * 542 * @param cms the current CMS context 543 * @return the list of available quick launch apps 544 */ 545 public List<I_CmsWorkplaceAppConfiguration> getQuickLaunchConfigurations(CmsObject cms) { 546 547 List<I_CmsWorkplaceAppConfiguration> result = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 548 result.addAll(getDefaultQuickLaunchConfigurations()); 549 result.addAll(getUserQuickLauchConfigurations(cms)); 550 Iterator<I_CmsWorkplaceAppConfiguration> it = result.iterator(); 551 while (it.hasNext()) { 552 I_CmsWorkplaceAppConfiguration appConfig = it.next(); 553 CmsAppVisibilityStatus visibility = appConfig.getVisibility(cms); 554 if (!visibility.isVisible()) { 555 it.remove(); 556 } 557 } 558 return result; 559 } 560 561 /** 562 * Returns the user icon helper.<p> 563 * 564 * @return the user icon helper 565 */ 566 public CmsUserIconHelper getUserIconHelper() { 567 568 return m_iconHelper; 569 } 570 571 /** 572 * Returns all available workplace apps.<p> 573 * 574 * @return the available workpllace apps 575 */ 576 public Collection<I_CmsWorkplaceAppConfiguration> getWorkplaceApps() { 577 578 return m_appsById.values(); 579 } 580 581 /** 582 * Returns the additional workplace CSS URIs.<p> 583 * 584 * @return the additional workplace CSS URIs 585 */ 586 public Collection<String> getWorkplaceCssUris() { 587 588 return m_workplaceCssUris; 589 } 590 591 /** 592 * Initializes the additional workplace CSS URIs.<p> 593 * They will be taken from the module parameter 'workplace-css' if present in any module.<p> 594 * 595 * @param moduleManager the module manager instance 596 */ 597 public void initWorkplaceCssUris(CmsModuleManager moduleManager) { 598 599 Set<String> cssUris = new HashSet<String>(); 600 for (CmsModule module : moduleManager.getAllInstalledModules()) { 601 String param = module.getParameter(WORKPLACE_CSS_PARAM); 602 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(param)) { 603 cssUris.add(param); 604 } 605 } 606 File cssFile = new File( 607 OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebApplication( 608 CmsStringUtil.joinPaths("resources", TOOLBAR_CSS))); 609 if (cssFile.exists()) { 610 cssUris.add(TOOLBAR_CSS); 611 } 612 m_workplaceCssUris = Collections.unmodifiableSet(cssUris); 613 } 614 615 /** 616 * Loads the workplace apps.<p> 617 */ 618 public void loadApps() { 619 620 m_appsById.clear(); 621 m_appCategories = loadCategories(); 622 addAppConfigurations(loadDefaultApps()); 623 addAppConfigurations(loadAppsUsingServiceLoader()); 624 addAppConfigurations(loadLegacyApps()); 625 } 626 627 /** 628 * Stores the given app setting within the users additional info.<p> 629 * 630 * @param cms the cms context 631 * @param type the app setting type, used as the settings key 632 * @param appSettings the settings to store 633 */ 634 public void storeAppSettings(CmsObject cms, Class<? extends I_CmsAppSettings> type, I_CmsAppSettings appSettings) { 635 636 CmsUser user = cms.getRequestContext().getCurrentUser(); 637 CmsUserSettings settings = new CmsUserSettings(user); 638 639 String currentSetting = settings.getAdditionalPreference(type.getName(), true); 640 String state = appSettings.getSettingsString(); 641 if (((state == null) && (currentSetting == null)) || ((state != null) && state.equals(currentSetting))) { 642 // nothing changed 643 return; 644 } 645 646 settings.setAdditionalPreference(type.getName(), state); 647 try { 648 settings.save(cms); 649 } catch (CmsException e) { 650 LOG.error("Failed to store workplace app settings for type " + type.getName(), e); 651 } 652 } 653 654 /** 655 * Returns the quick launch apps set for the current user.<p> 656 * 657 * @param cms the cms context 658 * 659 * @return the quick launch app configurations 660 */ 661 protected List<I_CmsWorkplaceAppConfiguration> getUserQuickLauchConfigurations(CmsObject cms) { 662 663 String apps_info = (String)cms.getRequestContext().getCurrentUser().getAdditionalInfo(QUICK_LAUCH_APPS_KEY); 664 String[] appIds = null; 665 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(apps_info)) { 666 try { 667 JSONArray ids = new JSONArray(apps_info); 668 appIds = new String[ids.length()]; 669 for (int i = 0; i < appIds.length; i++) { 670 appIds[i] = ids.getString(i); 671 } 672 } catch (JSONException e) { 673 LOG.error("Error parsing user quick launch apps setting.", e); 674 appIds = null; 675 } 676 } 677 return getAppConfigurations(appIds != null ? appIds : DEFAULT_USER_APPS); 678 } 679 680 /** 681 * Writes the user quick launch apps setting to the user additional info.<p> 682 * 683 * @param cms the cms context 684 * @param apps the app ids 685 * 686 * @throws Exception in case writing the user fails 687 */ 688 protected void setUserQuickLaunchApps(CmsObject cms, List<String> apps) throws Exception { 689 690 JSONArray appIds = new JSONArray(apps); 691 CmsUser user = cms.getRequestContext().getCurrentUser(); 692 String infoValue = appIds.toString(); 693 String previousApps = (String)user.getAdditionalInfo(QUICK_LAUCH_APPS_KEY); 694 // remove the additional info value to use default setting, in case the selected apps match the default apps 695 if (new JSONArray(DEFAULT_USER_APPS).toString().equals(infoValue)) { 696 infoValue = null; 697 } 698 // check if the additional info value needs to be changed 699 if ((infoValue == previousApps) || ((infoValue != null) && infoValue.equals(previousApps))) { 700 701 return; 702 } 703 if (infoValue == null) { 704 user.deleteAdditionalInfo(QUICK_LAUCH_APPS_KEY); 705 } else { 706 user.setAdditionalInfo(QUICK_LAUCH_APPS_KEY, infoValue); 707 } 708 cms.writeUser(user); 709 } 710 711 /** 712 * Adds the given app configuration.<p> 713 * 714 * @param appConfigs the app configuration 715 */ 716 private void addAppConfigurations(Collection<I_CmsWorkplaceAppConfiguration> appConfigs) { 717 718 for (I_CmsWorkplaceAppConfiguration appConfig : appConfigs) { 719 I_CmsWorkplaceAppConfiguration old = m_appsById.get(appConfig.getId()); 720 if ((old == null) || (old.getPriority() < appConfig.getPriority())) { 721 m_appsById.put(appConfig.getId(), appConfig); 722 } 723 } 724 } 725 726 /** 727 * Loads the App Folder.<p> 728 * 729 * @return list of all app folder 730 */ 731 private List<I_CmsFolderAppCategory> loadAppFolder() { 732 733 List<I_CmsFolderAppCategory> result = new ArrayList<I_CmsFolderAppCategory>(); 734 result.addAll( 735 Arrays.<I_CmsFolderAppCategory> asList( 736 new CmsLinkValidationFolder(), 737 new CmsDbManagerFolder(), 738 new CmsCacheFolder())); 739 return result; 740 } 741 742 /** 743 * Returns the configured apps using the service loader.<p> 744 * 745 * @return tthe configured apps 746 */ 747 private List<I_CmsWorkplaceAppConfiguration> loadAppsUsingServiceLoader() { 748 749 List<I_CmsWorkplaceAppConfiguration> appConfigurations = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 750 Iterator<I_CmsWorkplaceAppConfiguration> configs = ServiceLoader.load( 751 I_CmsWorkplaceAppConfiguration.class).iterator(); 752 while (configs.hasNext()) { 753 try { 754 I_CmsWorkplaceAppConfiguration config = configs.next(); 755 appConfigurations.add(config); 756 } catch (Throwable t) { 757 LOG.error("Error loading workplace app configuration from classpath.", t); 758 } 759 } 760 return appConfigurations; 761 } 762 763 /** 764 * Loads the app categories.<p> 765 * 766 * @return the app categories 767 */ 768 private Map<String, I_CmsAppCategory> loadCategories() { 769 770 Map<String, I_CmsAppCategory> appCategories = new HashMap<String, I_CmsAppCategory>(); 771 CmsAppCategory main = new CmsAppCategory(MAIN_CATEGORY_ID, null, 0, 0); 772 appCategories.put(main.getId(), main); 773 CmsAppCategory admin = new CmsAppCategory(ADMINISTRATION_CATEGORY_ID, null, 5, 0); 774 appCategories.put(admin.getId(), admin); 775 CmsAppCategory legacy = new CmsAppCategory(LEGACY_CATEGORY_ID, null, 10, 0); 776 appCategories.put(legacy.getId(), legacy); 777 List<I_CmsFolderAppCategory> folder = loadAppFolder(); 778 for (I_CmsFolderAppCategory appFolder : folder) { 779 appCategories.put(appFolder.getId(), appFolder); 780 } 781 Iterator<I_CmsAppCategory> categoryIt = ServiceLoader.load(I_CmsAppCategory.class).iterator(); 782 while (categoryIt.hasNext()) { 783 try { 784 I_CmsAppCategory cat = categoryIt.next(); 785 if (!appCategories.containsKey(cat.getId()) 786 || (appCategories.get(cat.getId()).getPriority() < cat.getPriority())) { 787 appCategories.put(cat.getId(), cat); 788 } 789 } catch (Throwable t) { 790 LOG.error("Error loading workplace app category from classpath.", t); 791 } 792 } 793 return appCategories; 794 } 795 796 /** 797 * Loads the default apps.<p> 798 * 799 * @return the default apps 800 */ 801 private Collection<I_CmsWorkplaceAppConfiguration> loadDefaultApps() { 802 803 List<I_CmsWorkplaceAppConfiguration> result = Lists.newArrayList(); 804 result.addAll( 805 Arrays.<I_CmsWorkplaceAppConfiguration> asList( 806 new CmsSitemapEditorConfiguration(), 807 new CmsPageEditorConfiguration(), 808 new CmsFileExplorerConfiguration(), 809 new CmsScheduledJobsAppConfig(), 810 new CmsAppHierarchyConfiguration(), 811 new CmsEditorConfiguration(), 812 new CmsQuickLaunchEditorConfiguration(), 813 new CmsProjectManagerConfiguration(), 814 new CmsProjectOverviewConfiguration(), 815 new CmsCacheAdminConfiguration(), 816 new CmsCacheViewFlexConfiguration(), 817 new CmsCacheViewImageConfiguration(), 818 new CmsFileHistoryConfiguration(), 819 new CmsLinkValidationConfiguration(), 820 new CmsLinkValidationExternalConfiguration(), 821 new CmsLinkInFolderValidationConfiguration(), 822 new CmsDbManagerConfiguration(), 823 new CmsDbImportHTTPConfiguration(), 824 new CmsDbImportServerConfiguration(), 825 new CmsDbExportConfiguration(), 826 new CmsDbStaticExportConfiguration(), 827 new CmsSqlConsoleAppConfiguration(), 828 new CmsDbRemovePubLocksConfiguration(), 829 new CmsDbSynchronizationConfiguration(), 830 new CmsDbPropertiesAppConfiguration(), 831 new CmsSearchindexAppConfiguration(), 832 new CmsLogFileConfiguration(), 833 new CmsSourceSearchAppConfiguration(), 834 new CmsListManagerConfiguration(), 835 new CmsSiteManagerConfiguration(), 836 new CmsPublishQueueConfiguration(), 837 new CmsGitAppConfiguration(), 838 new CmsBroadCastConfigurtion(), 839 new CmsModuleAppConfiguration(), 840 new CmsAccountsAppConfiguration(), 841 new CmsShellAppConfiguration(), 842 new CmsResourceTypeAppConfiguration(), 843 new CmsUserDataAppConfiguration(), 844 new CmsUnusedContentFinderConfiguration())); 845 846 return result; 847 } 848 849 /** 850 * Loads the legacy apps.<p> 851 * 852 * @return the legacy apps 853 */ 854 private Collection<I_CmsWorkplaceAppConfiguration> loadLegacyApps() { 855 856 List<I_CmsWorkplaceAppConfiguration> configs = new ArrayList<I_CmsWorkplaceAppConfiguration>(); 857 // avoid accessing the workplace manager during test case 858 if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_2_INITIALIZING) { 859 List<CmsTool> tools = OpenCms.getWorkplaceManager().getToolManager().getToolHandlers(); 860 for (CmsTool tool : tools) { 861 862 I_CmsToolHandler handler = tool.getHandler(); 863 String path = handler.getPath(); 864 865 // only collecting first path level tools 866 if ((path.length() > 1) && (path.indexOf(CmsToolManager.TOOLPATH_SEPARATOR, 1) < 0)) { 867 if (!LEGACY_BLACKLIST.contains(path)) { 868 configs.add(new CmsLegacyAppConfiguration(handler)); 869 } 870 } 871 872 } 873 } 874 return configs; 875 } 876 877}