Java tutorial
/** * Licensed to Jasig under one or more contributor license * agreements. See the NOTICE file distributed with this work * for additional information regarding copyright ownership. * Jasig licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a * copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.jasig.portal.layout.dlm.remoting; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jasig.portal.IUserIdentityStore; import org.jasig.portal.PortalException; import org.jasig.portal.UserPreferencesManager; import org.jasig.portal.fragment.subscribe.IUserFragmentSubscription; import org.jasig.portal.fragment.subscribe.dao.IUserFragmentSubscriptionDao; import org.jasig.portal.groups.IEntity; import org.jasig.portal.layout.IStylesheetUserPreferencesService; import org.jasig.portal.layout.IStylesheetUserPreferencesService.PreferencesScope; import org.jasig.portal.layout.IUserLayoutManager; import org.jasig.portal.layout.IUserLayoutStore; import org.jasig.portal.layout.dlm.Constants; import org.jasig.portal.layout.dlm.DistributedUserLayout; import org.jasig.portal.layout.dlm.UserPrefsHandler; import org.jasig.portal.layout.node.IUserLayoutChannelDescription; import org.jasig.portal.layout.node.IUserLayoutFolderDescription; import org.jasig.portal.layout.node.IUserLayoutNodeDescription; import org.jasig.portal.layout.node.UserLayoutChannelDescription; import org.jasig.portal.layout.node.UserLayoutFolderDescription; import org.jasig.portal.portlet.om.IPortletDefinition; import org.jasig.portal.portlet.registry.IPortletDefinitionRegistry; import org.jasig.portal.security.IAuthorizationPrincipal; import org.jasig.portal.security.IPerson; import org.jasig.portal.security.PersonFactory; import org.jasig.portal.security.provider.RestrictedPerson; import org.jasig.portal.services.AuthorizationService; import org.jasig.portal.services.GroupService; import org.jasig.portal.user.IUserInstance; import org.jasig.portal.user.IUserInstanceManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; 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.servlet.ModelAndView; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Provides targets for AJAX preference setting calls. * * @author jennifer.bourey@yale.edu * @version $Revision$ $Date$ */ @Controller @RequestMapping("/layout") public class UpdatePreferencesServlet { private static final String TAB_GROUP_PARAMETER = "tabGroup"; // matches incoming JS private static final String TAB_GROUP_DEFAULT = "DEFAULT_TABGROUP"; // matches default in structure transform private static final String ADDTAB_PERMISSION_OWNER = "UP_SYSTEM"; private static final String ADDTAB_PERMISSION_ACTIVITY = "ADD_TAB"; private static final String ADDTAB_PERMISSION_TARGET = "ALL"; protected final Log log = LogFactory.getLog(getClass()); private IPortletDefinitionRegistry portletDefinitionRegistry; private IUserIdentityStore userIdentityStore; private IUserFragmentSubscriptionDao userFragmentInfoDao; private IUserInstanceManager userInstanceManager; private IStylesheetUserPreferencesService stylesheetUserPreferencesService; private IUserLayoutStore userLayoutStore; @Autowired public void setUserLayoutStore(IUserLayoutStore userLayoutStore) { this.userLayoutStore = userLayoutStore; } @Autowired public void setStylesheetUserPreferencesService( IStylesheetUserPreferencesService stylesheetUserPreferencesService) { this.stylesheetUserPreferencesService = stylesheetUserPreferencesService; } @Autowired public void setPortletDefinitionRegistry(IPortletDefinitionRegistry portletDefinitionRegistry) { this.portletDefinitionRegistry = portletDefinitionRegistry; } @Autowired public void setUserIdentityStore(IUserIdentityStore userStore) { this.userIdentityStore = userStore; } @Autowired public void setUserFragmentInfoDao(IUserFragmentSubscriptionDao userFragmentInfoDao) { this.userFragmentInfoDao = userFragmentInfoDao; } @Autowired public void setUserInstanceManager(IUserInstanceManager userInstanceManager) { this.userInstanceManager = userInstanceManager; } // default tab name protected static final String DEFAULT_TAB_NAME = "New Tab"; /** * Remove an element from the layout. * * @param request * @param response * @return * @throws IOException */ @RequestMapping(method = RequestMethod.POST, params = "action=removeElement") public ModelAndView removeElement(HttpServletRequest request, HttpServletResponse response) throws IOException { IUserInstance ui = userInstanceManager.getUserInstance(request); IPerson per = getPerson(ui, response); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); try { // if the element ID starts with the fragment prefix and is a folder, // attempt first to treat it as a pulled fragment subscription String elementId = request.getParameter("elementID"); if (elementId != null && elementId.startsWith(Constants.FRAGMENT_ID_USER_PREFIX) && ulm.getNode(elementId) instanceof org.jasig.portal.layout.node.UserLayoutFolderDescription) { removeSubscription(per, elementId, ulm); } else { // Delete the requested element node. This code is the same for // all node types, so we can just have a generic action. ulm.deleteNode(elementId); } ulm.saveUserLayout(); return new ModelAndView("jsonView", Collections.EMPTY_MAP); } catch (Exception e) { log.warn("Failed to remove element from layout", e); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } } /** * Subscribe a user to a pre-formatted tab (pulled DLM fragment). * * @param request * @param response * @return * @throws IOException */ @RequestMapping(method = RequestMethod.POST, params = "action=subscribeToTab") public ModelAndView subscribeToTab(HttpServletRequest request, HttpServletResponse response) throws IOException { IUserInstance ui = userInstanceManager.getUserInstance(request); IPerson per = getPerson(ui, response); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); // Get the fragment owner's name from the request and construct // an IPerson object representing that user String fragmentOwnerName = request.getParameter("sourceID"); if (StringUtils.isBlank(fragmentOwnerName)) { log.warn("Attempted to subscribe to tab with null owner ID"); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } RestrictedPerson fragmentOwner = PersonFactory.createRestrictedPerson(); fragmentOwner.setUserName(fragmentOwnerName); // Mark the currently-authenticated user as subscribed to this fragment. // If an inactivated fragment registration already exists, update it // as an active subscription. Otherwise, create a new fragment // subscription. IUserFragmentSubscription userFragmentInfo = userFragmentInfoDao.getUserFragmentInfo(per, fragmentOwner); if (userFragmentInfo == null) { userFragmentInfo = userFragmentInfoDao.createUserFragmentInfo(per, fragmentOwner); } else { userFragmentInfo.setActive(true); userFragmentInfoDao.updateUserFragmentInfo(userFragmentInfo); } try { // reload user layout and stylesheet to incorporate new DLM fragment ulm.loadUserLayout(true); // get the target node this new tab should be moved after String destinationId = request.getParameter("elementID"); // get the user layout for the currently-authenticated user int uid = userIdentityStore.getPortalUID(fragmentOwner, false); final DistributedUserLayout userLayout = userLayoutStore.getUserLayout(per, upm.getUserProfile()); Document layoutDocument = userLayout.getLayout(); // attempt to find the new subscribed tab in the layout so we can // move it StringBuilder expression = new StringBuilder("//folder[@type='root']/folder[starts-with(@ID,'") .append(Constants.FRAGMENT_ID_USER_PREFIX).append(uid).append("')]"); XPathFactory fac = XPathFactory.newInstance(); XPath xpath = fac.newXPath(); NodeList nodes = (NodeList) xpath.evaluate(expression.toString(), layoutDocument, XPathConstants.NODESET); String sourceId = nodes.item(0).getAttributes().getNamedItem("ID").getTextContent(); ulm.moveNode(sourceId, ulm.getParentId(destinationId), destinationId); ulm.saveUserLayout(); return new ModelAndView("jsonView", Collections.singletonMap("tabId", sourceId)); } catch (Exception e) { log.warn("Error subscribing to fragment owned by " + fragmentOwnerName, e); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } } /** * Move a portlet to another location on the tab. * * @param ulm * @param request * @param response * @throws IOException * @throws PortalException */ @RequestMapping(method = RequestMethod.POST, params = "action=movePortlet") public ModelAndView movePortlet(HttpServletRequest request, HttpServletResponse response) throws IOException, PortalException { IUserInstance ui = userInstanceManager.getUserInstance(request); IPerson per = getPerson(ui, response); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); // portlet to be moved String sourceId = request.getParameter("sourceID"); // Either "insertBefore" or "appendAfter". String method = request.getParameter("method"); // Target element to move the source element in front of. This parameter // isn't actually relevant if we're appending the source element. String destinationId = request.getParameter("elementID"); if (isTab(ulm, destinationId)) { // if the target is a tab type node, move the portlet to // the end of the first column @SuppressWarnings("unchecked") Enumeration<String> columns = ulm.getChildIds(destinationId); if (columns.hasMoreElements()) { ulm.moveNode(sourceId, columns.nextElement(), null); } else { IUserLayoutFolderDescription newColumn = new UserLayoutFolderDescription(); newColumn.setName("Column"); newColumn.setId("tbd"); newColumn.setFolderType(IUserLayoutFolderDescription.REGULAR_TYPE); newColumn.setHidden(false); newColumn.setUnremovable(false); newColumn.setImmutable(false); // add the column to our layout IUserLayoutNodeDescription col = ulm.addNode(newColumn, destinationId, null); // move the channel ulm.moveNode(sourceId, col.getId(), null); } } else if (ulm.getRootFolderId().equals( // if the target is a column type node, we need to just move the portlet // to the end of the column ulm.getParentId(ulm.getParentId(destinationId)))) { ulm.moveNode(sourceId, destinationId, null); } else { // If we're moving this element before another one, we need // to know what the target is. If there's no target, just // assume we're moving it to the very end of the column. String siblingId = null; if (method.equals("insertBefore")) siblingId = destinationId; // move the node as requested and save the layout ulm.moveNode(sourceId, ulm.getParentId(destinationId), siblingId); } try { // save the user's layout ulm.saveUserLayout(); } catch (Exception e) { log.warn("Error saving layout", e); } return new ModelAndView("jsonView", Collections.EMPTY_MAP); } /** * Change the number of columns on a specified tab. In the event that the user is * decreasing the number of columns, extra columns will be stripped from the * right-hand side. Any channels in these columns will be moved to the bottom of * the last preserved column. * * @param per * @param upm * @param ulm * @param request * @param response * @throws IOException * @throws PortalException */ @RequestMapping(method = RequestMethod.POST, params = "action=changeColumns") public ModelAndView changeColumns(HttpServletRequest request, HttpServletResponse response, @RequestParam("tabId") String tabId, @RequestParam("widths[]") String[] widths, @RequestParam(value = "deleted[]", required = false) String[] deleted, @RequestParam(value = "acceptor", required = false) String acceptor) throws IOException, PortalException { IUserInstance ui = userInstanceManager.getUserInstance(request); IPerson per = getPerson(ui, response); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); int newColumnCount = widths.length; // build a list of the current columns for this tab @SuppressWarnings("unchecked") Enumeration<String> columns = ulm.getChildIds(tabId); List<String> columnList = new ArrayList<String>(); while (columns.hasMoreElements()) { columnList.add(columns.nextElement()); } int oldColumnCount = columnList.size(); Map<String, Object> model = new HashMap<String, Object>(); // if the new layout has more columns if (newColumnCount > oldColumnCount) { List<String> newColumnIds = new ArrayList<String>(); for (int i = columnList.size(); i < newColumnCount; i++) { // create new column element IUserLayoutFolderDescription newColumn = new UserLayoutFolderDescription(); newColumn.setName("Column"); newColumn.setId("tbd"); newColumn.setFolderType(IUserLayoutFolderDescription.REGULAR_TYPE); newColumn.setHidden(false); newColumn.setUnremovable(false); newColumn.setImmutable(false); // add the column to our layout IUserLayoutNodeDescription node = ulm.addNode(newColumn, tabId, null); newColumnIds.add(node.getId()); model.put("newColumnIds", newColumnIds); columnList.add(node.getId()); } } // if the new layout has fewer columns else if (deleted != null && deleted.length > 0) { if (columnList.size() != widths.length + deleted.length) { // TODO: error? } for (String columnId : deleted) { // move all channels in the current column to the last valid column @SuppressWarnings("unchecked") Enumeration channels = ulm.getChildIds(columnId); while (channels.hasMoreElements()) { ulm.addNode(ulm.getNode((String) channels.nextElement()), acceptor, null); } // delete the column from the user's layout ulm.deleteNode(columnId); columnList.remove(columnId); } } int count = 0; for (String columnId : columnList) { this.stylesheetUserPreferencesService.setLayoutAttribute(request, PreferencesScope.STRUCTURE, columnId, "width", widths[count] + "%"); try { // This sets the column attribute in memory but doesn't persist it. Comment says saves changes "prior to persisting" Element folder = ulm.getUserLayoutDOM().getElementById(columnId); UserPrefsHandler.setUserPreference(folder, "width", per); } catch (Exception e) { log.error("Error saving new column widths", e); } count++; } try { ulm.saveUserLayout(); } catch (Exception e) { log.warn("Error saving layout", e); } return new ModelAndView("jsonView", model); } /** * Move a tab left or right. * * @param per * @param upm * @param ulm * @param request * @param response * @throws PortalException * @throws IOException */ @RequestMapping(method = RequestMethod.POST, params = "action=moveTab") public ModelAndView moveTab(HttpServletRequest request, HttpServletResponse response) throws IOException { IUserInstance ui = userInstanceManager.getUserInstance(request); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); // gather the parameters we need to move a channel String destinationId = request.getParameter("elementID"); String sourceId = request.getParameter("sourceID"); String method = request.getParameter("method"); // If we're moving this element before another one, we need // to know what the target is. If there's no target, just // assume we're moving it to the very end of the list. String siblingId = null; if (method.equals("insertBefore")) siblingId = destinationId; // move the node as requested and save the layout ulm.moveNode(sourceId, ulm.getParentId(destinationId), siblingId); try { ulm.saveUserLayout(); } catch (Exception e) { log.warn("Failed to move tab in user layout", e); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } return new ModelAndView("jsonView", Collections.EMPTY_MAP); } /** * Add a new channel. * * @param per * @param upm * @param ulm * @param request * @param response * @throws IOException * @throws PortalException */ @RequestMapping(method = RequestMethod.POST, params = "action=addPortlet") public ModelAndView addPortlet(HttpServletRequest request, HttpServletResponse response) throws IOException, PortalException { IUserInstance ui = userInstanceManager.getUserInstance(request); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); // gather the parameters we need to move a channel String destinationId = request.getParameter("elementID"); String sourceId = request.getParameter("channelID"); String method = request.getParameter("position"); IPortletDefinition definition = portletDefinitionRegistry.getPortletDefinition(sourceId); IUserLayoutChannelDescription channel = new UserLayoutChannelDescription(definition); IUserLayoutNodeDescription node = null; if (isTab(ulm, destinationId)) { @SuppressWarnings("unchecked") Enumeration<String> columns = ulm.getChildIds(destinationId); if (columns.hasMoreElements()) { while (columns.hasMoreElements()) { // attempt to add this channel to the column node = ulm.addNode(channel, columns.nextElement(), null); // if it couldn't be added to this column, go on and try the next // one. otherwise, we're set. if (node != null) break; } } else { IUserLayoutFolderDescription newColumn = new UserLayoutFolderDescription(); newColumn.setName("Column"); newColumn.setId("tbd"); newColumn.setFolderType(IUserLayoutFolderDescription.REGULAR_TYPE); newColumn.setHidden(false); newColumn.setUnremovable(false); newColumn.setImmutable(false); // add the column to our layout IUserLayoutNodeDescription col = ulm.addNode(newColumn, destinationId, null); // add the channel node = ulm.addNode(channel, col.getId(), null); } } else if (isColumn(ulm, destinationId)) { // move the channel into the column node = ulm.addNode(channel, destinationId, null); } else { // If we're moving this element before another one, we need // to know what the target is. If there's no target, just // assume we're moving it to the very end of the column. String siblingId = null; if (method.equals("insertBefore")) siblingId = destinationId; // move the node as requested and save the layout node = ulm.addNode(channel, ulm.getParentId(destinationId), siblingId); } String nodeId = node.getId(); try { // save the user's layout ulm.saveUserLayout(); } catch (Exception e) { log.warn("Error saving layout", e); } Map<String, String> model = new HashMap<String, String>(); model.put("response", "Added new channel"); model.put("newNodeId", nodeId); return new ModelAndView("jsonView", model); } /** * Update the user's preferred skin. * * @param per * @param upm * @param ulm * @param request * @param response * @throws IOException * @throws PortalException */ @RequestMapping(method = RequestMethod.POST, params = "action=chooseSkin") public ModelAndView chooseSkin(HttpServletRequest request, HttpServletResponse response) throws IOException { String skinName = request.getParameter("skinName"); this.stylesheetUserPreferencesService.setStylesheetParameter(request, PreferencesScope.THEME, "skin", skinName); return new ModelAndView("jsonView", Collections.EMPTY_MAP); } /** * Add a new tab to the layout. The new tab will be appended to the end of the * list and named with the BLANK_TAB_NAME variable. * * @param request * @throws IOException */ @RequestMapping(method = RequestMethod.POST, params = "action=addTab") public ModelAndView addTab(HttpServletRequest request, HttpServletResponse response, @RequestParam("widths[]") String[] widths) throws IOException { IUserInstance ui = userInstanceManager.getUserInstance(request); IPerson per = getPerson(ui, response); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); // Verify that the user has permission to add this tab final IAuthorizationPrincipal authPrincipal = this.getUserPrincipal(per.getUserName()); if (!authPrincipal.hasPermission(ADDTAB_PERMISSION_OWNER, ADDTAB_PERMISSION_ACTIVITY, ADDTAB_PERMISSION_TARGET)) { log.warn("Attempt to add a tab through the REST API by unauthorized user '" + per.getUserName() + "'"); response.sendError(HttpServletResponse.SC_FORBIDDEN); return null; } // construct a brand new tab String id = "tbd"; String tabName = request.getParameter("tabName"); if (StringUtils.isBlank(tabName)) tabName = DEFAULT_TAB_NAME; IUserLayoutFolderDescription newTab = new UserLayoutFolderDescription(); newTab.setName(tabName); newTab.setId(id); newTab.setFolderType(IUserLayoutFolderDescription.REGULAR_TYPE); newTab.setHidden(false); newTab.setUnremovable(false); newTab.setImmutable(false); // add the tab to the layout ulm.addNode(newTab, ulm.getRootFolderId(), null); try { // save the user's layout ulm.saveUserLayout(); } catch (Exception e) { log.warn("Error saving layout", e); } // get the id of the newly added tab String tabId = newTab.getId(); for (String width : widths) { // create new column element IUserLayoutFolderDescription newColumn = new UserLayoutFolderDescription(); newColumn.setName("Column"); newColumn.setId("tbd"); newColumn.setFolderType(IUserLayoutFolderDescription.REGULAR_TYPE); newColumn.setHidden(false); newColumn.setUnremovable(false); newColumn.setImmutable(false); // add the column to our layout ulm.addNode(newColumn, tabId, null); this.stylesheetUserPreferencesService.setLayoutAttribute(request, PreferencesScope.STRUCTURE, newColumn.getId(), "width", width + "%"); try { // This sets the column attribute in memory but doesn't persist it. Comment says saves changes "prior to persisting" Element folder = ulm.getUserLayoutDOM().getElementById(newColumn.getId()); UserPrefsHandler.setUserPreference(folder, "width", per); } catch (Exception e) { log.error("Error saving new column widths", e); } } // ## 'tabGroup' value (optional feature) // Set the 'tabGroup' attribute on the folder element that describes // this new tab; use the currently active tabGroup. if (request.getParameter(TAB_GROUP_PARAMETER) != null) { String tabGroup = request.getParameter(TAB_GROUP_PARAMETER).trim(); if (log.isDebugEnabled()) { log.debug(TAB_GROUP_PARAMETER + "=" + tabGroup); } if (!TAB_GROUP_DEFAULT.equals(tabGroup) && tabGroup.length() != 0) { // Persists SSUP values to the database this.stylesheetUserPreferencesService.setLayoutAttribute(request, PreferencesScope.STRUCTURE, tabId, TAB_GROUP_PARAMETER, tabGroup); } } try { // save the user's layout ulm.saveUserLayout(); } catch (Exception e) { log.warn("Error saving layout", e); } return new ModelAndView("jsonView", Collections.singletonMap("tabId", tabId)); } /** * Rename a specified tab. * * @param request * @throws IOException */ @RequestMapping(method = RequestMethod.POST, params = "action=renameTab") public ModelAndView renameTab(HttpServletRequest request, HttpServletResponse response) throws IOException { IUserInstance ui = userInstanceManager.getUserInstance(request); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); // element ID of the tab to be renamed String tabId = request.getParameter("tabId"); IUserLayoutFolderDescription tab = (IUserLayoutFolderDescription) ulm.getNode(tabId); // desired new name String tabName = request.getParameter("tabName"); if (!ulm.canUpdateNode(tab)) { log.warn("Attempting to rename an immutable tab"); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } /* * Update the tab and save the layout */ tab.setName(StringUtils.isBlank(tabName) ? DEFAULT_TAB_NAME : tabName); final boolean updated = ulm.updateNode(tab); if (updated) { try { // save the user's layout ulm.saveUserLayout(); } catch (Exception e) { log.warn("Error saving layout", e); } //TODO why do we have to do this, shouldn't modifying the layout be enough to trigger a full re-render (layout's cache key changes) this.stylesheetUserPreferencesService.setLayoutAttribute(request, PreferencesScope.STRUCTURE, tabId, "name", tabName); } Map<String, String> model = Collections.singletonMap("message", "saved new tab name"); return new ModelAndView("jsonView", model); } @RequestMapping(method = RequestMethod.POST, params = "action=updatePermissions") public ModelAndView updatePermissions(HttpServletRequest request, HttpServletResponse response) throws IOException { IUserInstance ui = userInstanceManager.getUserInstance(request); UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager(); IUserLayoutManager ulm = upm.getUserLayoutManager(); String elementId = request.getParameter("elementID"); IUserLayoutNodeDescription node = ulm.getNode(elementId); if (node == null) { log.warn("Failed to locate node for permissions update"); response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } String deletable = request.getParameter("deletable"); if (!StringUtils.isBlank(deletable)) { node.setDeleteAllowed(Boolean.valueOf(deletable)); } String movable = request.getParameter("movable"); if (!StringUtils.isBlank(movable)) { node.setMoveAllowed(Boolean.valueOf(movable)); } String editable = request.getParameter("editable"); if (!StringUtils.isBlank(editable)) { node.setEditAllowed(Boolean.valueOf(editable)); } String canAddChildren = request.getParameter("addChildAllowed"); if (!StringUtils.isBlank(canAddChildren)) { node.setAddChildAllowed(Boolean.valueOf(canAddChildren)); } ulm.updateNode(node); try { // save the user's layout ulm.saveUserLayout(); } catch (Exception e) { log.warn("Error saving layout", e); } return new ModelAndView("jsonView", Collections.EMPTY_MAP); } protected void removeSubscription(IPerson per, String elementId, IUserLayoutManager ulm) { // get the fragment owner's ID from the element string String userIdString = StringUtils.substringBetween(elementId, Constants.FRAGMENT_ID_USER_PREFIX, Constants.FRAGMENT_ID_LAYOUT_PREFIX); int userId = NumberUtils.toInt(userIdString, 0); // construct a new person object representing the fragment owner RestrictedPerson fragmentOwner = PersonFactory.createRestrictedPerson(); fragmentOwner.setID(userId); fragmentOwner.setUserName(userIdentityStore.getPortalUserName(userId)); // attempt to find a subscription for this fragment IUserFragmentSubscription subscription = userFragmentInfoDao.getUserFragmentInfo(per, fragmentOwner); // if a subscription was found, remove it's registration if (subscription != null) { userFragmentInfoDao.deleteUserFragmentInfo(subscription); ulm.loadUserLayout(true); } // otherwise, delete the node else { ulm.deleteNode(elementId); } } /** * A folder is a tab if its parent element is the layout element * * @param folder the folder in question * @return <code>true</code> if the folder is a tab, otherwise <code>false</code> */ protected boolean isTab(IUserLayoutManager ulm, String folderId) throws PortalException { // we could be a bit more careful here and actually check the type return ulm.getRootFolderId().equals(ulm.getParentId(folderId)); } protected IPerson getPerson(IUserInstance ui, HttpServletResponse response) throws IOException { IPerson per = ui.getPerson(); if (per.isGuest()) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return null; } return per; } protected IAuthorizationPrincipal getUserPrincipal(final String userName) { final IEntity user = GroupService.getEntity(userName, IPerson.class); if (user == null) { return null; } final AuthorizationService authService = AuthorizationService.instance(); return authService.newPrincipal(user); } /** * A folder is a column if its parent is a tab element * * @param folder the folder in question * @return <code>true</code> if the folder is a column, otherwise <code>false</code> */ protected boolean isColumn(IUserLayoutManager ulm, String folderId) throws PortalException { return isTab(ulm, ulm.getParentId(folderId)); } }