/* * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package com.arsdigita.cms.ui.folder; import com.arsdigita.bebop.ActionLink; import com.arsdigita.bebop.Form; import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Page; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.ParameterSingleSelectionModel; import com.arsdigita.bebop.Resettable; import com.arsdigita.bebop.SegmentedPanel; import com.arsdigita.bebop.SingleSelectionModel; import com.arsdigita.bebop.event.ActionEvent; import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.ChangeEvent; import com.arsdigita.bebop.event.ChangeListener; import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormSubmissionListener; import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.bebop.parameters.BigDecimalParameter; import com.arsdigita.cms.CMS; import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.Folder; import com.arsdigita.cms.SecurityManager; import com.arsdigita.cms.dispatcher.Utilities; import com.arsdigita.cms.ui.authoring.CreationSelector; import com.arsdigita.cms.ui.authoring.NewItemForm; import com.arsdigita.cms.ui.permissions.CMSPermissionsPane; import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.kernel.ACSObject; import com.arsdigita.kernel.KernelHelper; import com.arsdigita.kernel.User; import com.arsdigita.kernel.permissions.ObjectPermissionCollection; import com.arsdigita.kernel.permissions.PermissionDescriptor; import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.DataQuery; import com.arsdigita.persistence.SessionManager; import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.util.Assert; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Encapsulates a {@link FolderManipulator} in order to create a flat * item listing. Also contains a new item form. * * @author Stanislav Freidin * @version $Revision: #6 $ $DateTime: 2004/08/17 23:15:09 $ * @version Id: FolderItemPane.java 287 2005-02-22 00:29:02Z sskracic $ */ public class FolderItemPane extends SegmentedPanel implements FormProcessListener, ChangeListener, FormSubmissionListener, Resettable, ActionListener { private static final String CONTENT_TYPE_ID = "ct"; private static final String CMS_PRIVILEGES = "com.arsdigita.cms.getPrivileges"; private static final String PRIVILEGE = "privilege"; private static final String PRIVILEGE_NAME = "prettyName"; //maximum number of items displayed in the table at a time public static int LIST_SIZE = 20; private NewItemForm m_newItem; private SingleSelectionModel m_typeSel; private FolderSelectionModel m_folderSel; private CreationSelector m_selector; private FolderManipulator m_folderManip; private FolderCreator m_folderCreator; private ActionLink m_createFolderAction; private ActionLink m_togglePrivateAction; private Segment m_browseSeg; private Segment m_newItemSeg; private Segment m_newFolderSeg; private Segment m_editFolderSeg; private Segment m_permissionsSeg; private CMSPermissionsPane m_permPane; // Folder edit/rename functionality. private ActionLink m_editFolderAction; private FolderEditor m_folderEditor; private Label m_contentLabel; private Label m_itemPath; private Label m_chooseLabel; /** * Create a new item listing pane. The listing creates its own {@link * FolderSelectionModel} to keep track of the currently selected * folder. This requires that this list is used within a content * section. The section's root folder is used as the starting point for * browsing. */ public FolderItemPane() { this(new FolderSelectionModel("folder")); } /** * Construct a new item listing pane. The provided folder selection model * is used to keep track of the currently displayed folder. * * @param folderSel maintains the currently displayed folder. */ public FolderItemPane(FolderSelectionModel folderSel) { super(); setIdAttr("flat-item-list"); m_folderSel = folderSel; m_newItemSeg = addSegment(); m_newItemSeg.setIdAttr("folder-new-item"); m_newFolderSeg = addSegment(); m_newFolderSeg.setIdAttr("folder-new-folder"); m_editFolderSeg = addSegment(); m_editFolderSeg.setIdAttr("folder-edit-folder"); m_browseSeg = addSegment(); m_browseSeg.setIdAttr("folder-browse"); final ActionGroup browseActions = new ActionGroup(); m_browseSeg.add(browseActions); // The top 'browse' segment m_contentLabel = new Label(globalize("cms.ui.contents_of"), false); m_browseSeg.addHeader(m_contentLabel); m_chooseLabel = new Label(globalize("cms.ui.choose_target_folder"), false); m_browseSeg.addHeader(m_chooseLabel); m_itemPath = new Label(new PrintListener() { public final void prepare(final PrintEvent e) { final Folder f = (Folder) m_folderSel.getSelectedObject (e.getPageState()); ((Label) e.getTarget()).setLabel(f.getDisplayName()); } }); m_browseSeg.addHeader(m_itemPath); m_folderManip = new FolderManipulator(m_folderSel); m_folderManip.getItemView().addProcessListener(this); m_folderManip.getTargetSelector().addProcessListener(this); m_folderManip.getTargetSelector().addSubmissionListener(this); browseActions.setSubject(m_folderManip); // The actions m_createFolderAction = new ActionLink(new Label(globalize("cms.ui.new_folder"))); m_createFolderAction.addActionListener(this); browseActions.addAction(m_createFolderAction); m_editFolderAction = new ActionLink(new Label(globalize("cms.ui.edit_folder"))); m_editFolderAction.addActionListener(this); browseActions.addAction(m_editFolderAction); m_newItem = new SectionNewItemForm("newItem"); m_newItem.addProcessListener(this); browseActions.addAction(m_newItem); m_permissionsSeg = addSegment(); m_permissionsSeg.setIdAttr("folder-permissions"); final ActionGroup permActions = new ActionGroup(); m_permissionsSeg.add(permActions); // The permissions segment m_permissionsSeg.addHeader(new Label(GlobalizationUtil.globalize("cms.ui.permissions"))); List privs = new ArrayList(); Map privNameMap = new HashMap(); DataQuery query = SessionManager.getSession().retrieveQuery(CMS_PRIVILEGES); query.addFilter("scope != 'section'"); query.addOrder("sortOrder"); while (query.next()) { String privilege = (String) query.get(PRIVILEGE); String privilegeName = (String) query.get(PRIVILEGE_NAME); privs.add(PrivilegeDescriptor.get(privilege)); privNameMap.put(privilege, privilegeName); } query.close(); m_permPane = new CMSPermissionsPane ((PrivilegeDescriptor[]) privs.toArray(new PrivilegeDescriptor[privs.size()]), privNameMap, m_folderSel); permActions.setSubject(m_permPane); // An action m_togglePrivateAction = new ActionLink(new Label(new PrintListener() { public void prepare(PrintEvent e) { PageState state = e.getPageState(); Label target = (Label) e.getTarget(); Folder currentFolder = (Folder) m_folderSel.getSelectedObject(state); // ACSObject parent = currentFolder.getParent(); DataObject context = PermissionService.getContext(currentFolder); if (context == null) { target.setLabel( (String) GlobalizationUtil.globalize("cms.ui.restore_default_permissions").localize()); } else { target.setLabel( (String) GlobalizationUtil.globalize("cms.ui.use_custom_permissions").localize()); } } })); m_togglePrivateAction.addActionListener(this); permActions.addAction(m_togglePrivateAction); // The 'new item' segment m_newItemSeg.addHeader(new Label(globalize("cms.ui.new_item"))); m_typeSel = new ParameterSingleSelectionModel(new BigDecimalParameter(CONTENT_TYPE_ID)); m_typeSel.addChangeListener(this); m_selector = new CreationSelector(m_typeSel, m_folderSel); m_newItemSeg.add(m_selector); m_newItemSeg.add(new Label("
", false)); // The 'new folder' segment m_newFolderSeg.addHeader(new Label(globalize("cms.ui.new_folder"))); Form folderCreate = new Form("fcreat"); m_folderCreator = new FolderCreator("fcreat", m_folderSel); m_folderCreator.addSubmissionListener(this); m_folderCreator.addProcessListener(this); folderCreate.add(m_folderCreator); m_newFolderSeg.add(folderCreate); m_newFolderSeg.add(new Label("
", false)); m_editFolderSeg.addHeader(new Label(globalize("cms.ui.edit_folder"))); m_folderEditor = new FolderEditor("fedit", m_folderSel); m_folderEditor.addSubmissionListener(this); m_folderEditor.addProcessListener(this); Form folderEditorForm = new Form( "fedit_form" ); folderEditorForm.add( m_folderEditor ); m_editFolderSeg.add(folderEditorForm); m_editFolderSeg.add(new Label("
", false)); } public void register(Page p) { super.register(p); p.setVisibleDefault(m_chooseLabel, false); p.setVisibleDefault(m_newItemSeg, false); p.setVisibleDefault(m_newFolderSeg, false); p.setVisibleDefault(m_editFolderSeg, false); p.addComponentStateParam(this, m_typeSel.getStateParameter()); p.addComponentStateParam(this, m_folderSel.getStateParameter()); p.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { if (!event.getPageState().isVisibleOnPage(FolderItemPane.this)) { return; } showHideSegments(event.getPageState()); } }); } /** * Show/hide segments based on access checks. * * @param state The page state * @pre ( state != null ) */ private void showHideSegments(PageState state) { SecurityManager sm = Utilities.getSecurityManager(state); Folder folder = (Folder) m_folderSel.getSelectedObject(state); Assert.exists(folder); // MP: This should be checked on the current folder instead of just // the content section. boolean newItem = sm.canAccess(state.getRequest(), SecurityManager.NEW_ITEM, folder); if (!newItem) { browseMode(state); } m_createFolderAction.setVisible(state, newItem); m_newItem.setVisible(state, newItem); final boolean editItem = sm.canAccess(state.getRequest(), SecurityManager.EDIT_ITEM, folder); m_editFolderAction.setVisible(state, editItem); User user = KernelHelper.getCurrentUser(state.getRequest()); PermissionDescriptor perm = new PermissionDescriptor(PrivilegeDescriptor.ADMIN, folder, user); if (PermissionService.checkPermission(perm)) { m_permissionsSeg.setVisible(state, true); } else { m_permissionsSeg.setVisible(state, false); } } private void browseMode(PageState s) { m_browseSeg.setVisible(s, true); m_permissionsSeg.setVisible(s, true); m_chooseLabel.setVisible(s, false); m_contentLabel.setVisible(s, true); m_itemPath.setVisible(s, true); m_newItemSeg.setVisible(s, false); m_newFolderSeg.setVisible(s, false); m_editFolderSeg.setVisible(s, false); m_typeSel.clearSelection(s); } private void newItemMode(PageState s) { m_permissionsSeg.setVisible(s, false); m_newItemSeg.setVisible(s, true); } private void newFolderMode(PageState s) { m_permissionsSeg.setVisible(s, false); m_newFolderSeg.setVisible(s, true); } public void submitted(FormSectionEvent e) throws FormProcessException { PageState s = e.getPageState(); if ( e.getSource() == m_folderCreator && m_folderCreator.isCancelled(s) ) { browseMode(s); throw new FormProcessException( (String) GlobalizationUtil.globalize("cms.ui.cancelled").localize()); } else if (e.getSource() == m_folderEditor && m_folderEditor.isCancelled(s)) { browseMode(s); throw new FormProcessException( (String) GlobalizationUtil.globalize("cms.ui.cancelled").localize()); } else if ( e.getSource() == m_folderManip.getTargetSelector() ) { // This only works if this submission listener is run // after the target selector's one if ( ! m_folderManip.getTargetSelector().isVisible(s) ) { browseMode(s); } } } public void process(FormSectionEvent e) { PageState s = e.getPageState(); final Object source = e.getSource(); if (source == m_newItem) { BigDecimal typeID = m_newItem.getTypeID(s); m_typeSel.setSelectedKey(s, typeID); newItemMode(s); } else if (source == m_folderCreator || source == m_folderEditor) { browseMode(s); } else if (source == m_folderManip.getItemView()) { // Hide everything except for the browseSeg m_permissionsSeg.setVisible(s, false); m_chooseLabel.setVisible(s, true); m_contentLabel.setVisible(s, false); m_itemPath.setVisible(s, false); } else if (source == m_folderManip.getTargetSelector()) { browseMode(s); } } public void stateChanged(ChangeEvent e) { PageState s = e.getPageState(); if ( e.getSource() == m_typeSel ) { if ( ! m_typeSel.isSelected(s) ) { browseMode(s); } } } public void actionPerformed(ActionEvent e) { PageState s = e.getPageState(); Object source = e.getSource(); if ( source == m_createFolderAction ) { newFolderMode(s); } else if (source == m_editFolderAction) { m_permissionsSeg.setVisible(s, false); m_editFolderSeg.setVisible(s, true); } else if (source == m_togglePrivateAction) { togglePermissions(s); } } private void togglePermissions(PageState state) { Folder currentFolder = (Folder) m_folderSel.getSelectedObject(state); if (!Utilities.getSecurityManager(state).canAccess(state.getRequest(), SecurityManager.STAFF_ADMIN)) { throw new com.arsdigita.cms.dispatcher.AccessDeniedException(); } DataObject context = PermissionService.getContext(currentFolder); if (context != null) { PermissionService.clonePermissions(currentFolder); Folder liveFolder = (Folder) currentFolder.getLiveVersion(); if (liveFolder != null) { PermissionService.clonePermissions(liveFolder); } } else { ACSObject parent = currentFolder.getParent(); if (parent != null) { PermissionService.setContext(currentFolder, parent); } else { // if the folder has no parent, it must be a root folder or template folder // in this case, set it's context to the ContentSection ContentSection section = currentFolder.getContentSection(); if (section != null) { PermissionService.setContext(currentFolder, section); } else { throw new IllegalStateException("Cannot set the context for a folder with " + "no parent and no Content Section"); } } Folder liveVersion = (Folder) currentFolder.getLiveVersion(); if (liveVersion != null) { ACSObject liveParent = liveVersion.getParent(); if (liveParent != null) { PermissionService.setContext(liveVersion, liveParent); } else { ContentSection liveSection = liveVersion.getContentSection(); if (liveSection != null) { PermissionService.setContext(liveVersion, liveSection); } else { throw new IllegalStateException("Cannot set the context for a folder with " + "no parent and no Content Section"); } } } // revoke all direct permissions so folder will only have inherited permissions ObjectPermissionCollection perms = PermissionService.getGrantedPermissions(currentFolder.getOID()); while (perms.next()) { if (!perms.isInherited() && !perms.getPrivilege().equals(PrivilegeDescriptor.ADMIN)) { PermissionDescriptor desc = new PermissionDescriptor(perms.getPrivilege(), currentFolder.getOID(), perms.getGranteeOID()); PermissionService.revokePermission(desc); } } if (liveVersion != null) { ObjectPermissionCollection livePerms = PermissionService.getGrantedPermissions(liveVersion.getOID()); while (livePerms.next()) { if (!livePerms.isInherited()) { PermissionDescriptor desc2 = new PermissionDescriptor(livePerms.getPrivilege(), liveVersion.getOID(), livePerms.getGranteeOID()); PermissionService.revokePermission(desc2); } } } } m_permPane.reset(state); } public void reset(PageState s) { browseMode(s); m_folderSel.clearSelection(s); m_folderManip.reset(s); } public final FolderManipulator getManipulator() { return m_folderManip; } public final CMSPermissionsPane getPermissionsPane() { return m_permPane; } public void setPermissionLinkVis(PageState state) { if (!Utilities.getSecurityManager(state). canAccess(state.getRequest(), SecurityManager.STAFF_ADMIN)) { m_togglePrivateAction.setVisible(state, false); } } private static class SectionNewItemForm extends NewItemForm { public SectionNewItemForm(String name) { super(name); } public ContentSection getContentSection(PageState s) { return CMS.getContext().getContentSection(); } } /** * Getting the GlobalizedMessage using a CMS Class targetBundle. * * @param key The resource key * @pre ( key != null ) */ private static GlobalizedMessage globalize(String key) { return com.arsdigita.cms.ui.ContentSectionPage.globalize(key); } }