libreccm-legacy/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderItemPane.java

527 lines
21 KiB
Java
Executable File

/*
* 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 <a href="mailto:sfreidin@arsdigita.com">Stanislav Freidin</a>
* @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("<br/>", 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("<br/>", 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("<br/>", 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);
}
}