/** * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2009-2010], VMware, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * */ package org.hyperic.hq.web.dashboard; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.auth.shared.SessionNotFoundException; import org.hyperic.hq.auth.shared.SessionTimeoutException; import org.hyperic.hq.authz.shared.PermissionException; import org.hyperic.hq.bizapp.shared.AuthzBoss; import org.hyperic.hq.ui.WebUser; import org.hyperic.hq.ui.shared.DashboardManager; import org.hyperic.hq.ui.util.ConfigurationProxy; import org.hyperic.util.config.ConfigResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; /** * This controller handles all interactions relative to the dashboard. * * @author David Crutchfield * */ @Controller public class DashboardController extends BaseDashboardController { private final static Log log = LogFactory.getLog(DashboardController.class .getName()); private final static String TOKEN_DELIMITER = "_"; private final static String PORTLET_NAME_DELIMITER = "|"; private List<String> multiplePortletsList; @Autowired public DashboardController(AuthzBoss authzBoss, ConfigurationProxy configurationProxy, DashboardManager dashboardManager) { super(null, authzBoss, configurationProxy, dashboardManager, null, null); } public void setMultiplePortletsList(List<String> multiplePortletsList) { this.multiplePortletsList = multiplePortletsList; } // ...helper function to convert a delimited string of portlet names to a // List of Strings... private List<String> deconstructDelimitedStringOfPortletNames( String delimitedStringOfPortletNames) { return new ArrayList<String>( Arrays .asList(deconstructDelimitedStringToStringArray(delimitedStringOfPortletNames))); } // ...helper function to convert an String array of portlet names to a // delimited string... private String constructDelimitedStringOfPortletNames( List<String> portletNames) { return constructDelimitedString(portletNames .toArray(new String[portletNames.size()]), false); } @RequestMapping(method = RequestMethod.GET, value = "/dashboard/{dashboardId}/portlets") public @ResponseBody Map<String, Object> getDashboardPortlet(@PathVariable Integer dashboardId) { return new HashMap<String, Object>(); } @RequestMapping(method = RequestMethod.POST, value = "/dashboard/{dashboardId}/portlets") public String addPortletToDashboard(@PathVariable Integer dashboardId, @RequestParam(RequestParameterKeys.PORTLET_NAME) String portletName, @RequestParam(RequestParameterKeys.IS_PORTLET_WIDE) Boolean isWide, HttpSession session) { WebUser webUser = getWebUser(session); ConfigResponse dashboardSettings = getDashboardSettings(dashboardId, webUser); String userPreferenceKey; // ...determine which portlet column we're dealing with... if (isWide) { userPreferenceKey = UserPreferenceKeys.WIDE_PORTLETS_NG; } else { userPreferenceKey = UserPreferenceKeys.NARROW_PORTLETS_NG; } // ...then grab the list of associated portlets... String delimitedStringOfPortletNames = dashboardSettings .getValue(userPreferenceKey); // ...convert the delimited list of portlet names to an actual List... List<String> currentDashboardPortlets = deconstructDelimitedStringOfPortletNames(delimitedStringOfPortletNames); // ...check if the portlet to add, can be added multiple times OR not // already in the list... if (multiplePortletsList.contains(portletName) || !currentDashboardPortlets.contains(portletName)) { // ...add the requested portlet to the list of dashboard portlets, // and in the event there can be // multiple portlets make sure to make the name unique by appending // an index to the name (index // does not imply ordering, just makes the name unique... int index = 2; // Index starts at two since the first portlet would // already exist in the list String uniquePortletName = portletName; while (currentDashboardPortlets.contains(uniquePortletName)) { // ...increment the index until we stop getting a hit... uniquePortletName = portletName + TOKEN_DELIMITER + index++; } // ...update the list of dashboard portlets... currentDashboardPortlets.add(uniquePortletName); // ...create the map of updated settings // TODO probably should create a representation object for this Map<String, Object> updatedSettings = new HashMap<String, Object>(); updatedSettings .put( userPreferenceKey, constructDelimitedStringOfPortletNames(currentDashboardPortlets)); try { boolean updated = compareAndUpdateSettings(session, dashboardSettings, updatedSettings); if (updated) { log.debug("[" + portletName + "] added to dashboard [" + dashboardId + "] successfully"); } } catch (PermissionException e) { log .debug( "User doesn't have the permission to perform this operation", e); } catch (SessionNotFoundException e) { log.debug("User's session can't be found", e); } catch (SessionTimeoutException e) { log.debug("User's session has timed out", e); } catch (Exception e) { log.debug(e); } } // TODO loop back when we convert the dashboard over to MVC // return "redirect:/Dashboard.do"; // For Struts2 redirect return "redirect:/Dashboard.action"; } @RequestMapping(method = RequestMethod.DELETE, value = "/dashboard/{dashboardId}/portlets/{portletName:.*}") public String removePortletFromDashboard(@PathVariable Integer dashboardId, @PathVariable String portletName, HttpSession session) { WebUser webUser = getWebUser(session); ConfigResponse dashboardSettings = getDashboardSettings(dashboardId, webUser); // ...grab the lists of all dashboard portlets... /* List<String> narrowDashboardPortlets = deconstructDelimitedStringOfPortletNames(dashboardSettings .getValue(UserPreferenceKeys.NARROW_PORTLETS)); List<String> wideDashboardPortlets = deconstructDelimitedStringOfPortletNames(dashboardSettings .getValue(UserPreferenceKeys.WIDE_PORTLETS)); */ List<String> narrowDashboardPortlets = deconstructDelimitedStringOfPortletNames(dashboardSettings.getValue(UserPreferenceKeys.NARROW_PORTLETS_NG)); List<String> wideDashboardPortlets = deconstructDelimitedStringOfPortletNames(dashboardSettings.getValue(UserPreferenceKeys.WIDE_PORTLETS_NG)); // ...search and destroy... if (narrowDashboardPortlets.remove(portletName) || wideDashboardPortlets.remove(portletName)) { // ...if we get a hit, also clean up that portlet's settings... // TODO portlet preferences are stored as <portlet name>.<pref // name>[_<index>] // this makes it a little harder than it has to be, would like to // move portlets into the db // and manage the dashboard, portlet, preference relationship there // rather than in the // preference name, for now we'll use a regex to match associated // settings // ...get the base portlet name and token, if any... String[] portletNameTokens = portletName.split(TOKEN_DELIMITER); // ...setup the regex starting with the basename... // String regex = PORTLET_NAME_DELIMITER + portletNameTokens[0].toLowerCase(); // String regex = portletNameTokens[0].toLowerCase(); // ...make sure we include the end of the string in the mix... // regex += "$"; // ...create the map of updated settings // TODO probably should create a representation object for this Map<String, Object> updatedSettings = new HashMap<String, Object>(); // ...add modified portlet lists to updated settings map... updatedSettings.put(UserPreferenceKeys.NARROW_PORTLETS_NG, constructDelimitedStringOfPortletNames(narrowDashboardPortlets)); updatedSettings.put(UserPreferenceKeys.WIDE_PORTLETS_NG, constructDelimitedStringOfPortletNames(wideDashboardPortlets)); // ...now iterate thru the dashboard's setting keys... String regex = portletNameTokens[0].toLowerCase(); boolean mutlipleProtletIndicator=false; String portletIdentifer = null; if (portletNameTokens.length == 2) { // Indicates we are removing a multiple portlet mutlipleProtletIndicator = true; portletIdentifer = TOKEN_DELIMITER + portletNameTokens[1].toLowerCase(); } for (String settingKey : dashboardSettings.getKeys()) { String theKey = settingKey.toLowerCase(); if (mutlipleProtletIndicator){ if (theKey.contains((regex)) && theKey.contains((portletIdentifer)) ) { // ...we have a hit, so remove it... updatedSettings.put(settingKey, null); } } else { if ( theKey.contains((regex)) && !theKey.contains((TOKEN_DELIMITER)) ) { // ...we have a hit, so remove it... updatedSettings.put(settingKey, null); } } } try { boolean updated = compareAndUpdateSettings(session, dashboardSettings, updatedSettings); if (updated) { log.debug("[" + portletName + "] remove from dashboard [" + dashboardId + "] successfully"); } } catch (PermissionException e) { log.debug("User doesn't have the permission to perform this operation", e); } catch (SessionNotFoundException e) { log.debug("User's session can't be found", e); } catch (SessionTimeoutException e) { log.debug("User's session has timed out", e); } catch (Exception e) { log.debug(e); } } // ...now we're done, 302 out of here... return "redirect:/app/dashboard/" + dashboardId + "/portlets"; } }