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