blob: 158dd596a7ff0b684e356c7bea7d674c6c4545ba [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.apache.chemistry.opencmis.workbench;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.commons.SessionParameter;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.definitions.PermissionDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlEntryImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlPrincipalDataImpl;
import org.apache.chemistry.opencmis.workbench.model.ClientModel;
public class AclEditorFrame extends JFrame {
private static final long serialVersionUID = 1L;
private static final String WINDOW_TITLE = "ACL Editor";
private static final ImageIcon ICON_ADD = ClientHelper.getIcon("add.png");
private final ClientModel model;
private final CmisObject object;
private final AceList addAceList;
private final AceList removeAceList;
private JRadioButton propagationRepositoryButton;
private JRadioButton propagationObjectOnlyButton;
private JRadioButton propagationPropagteButton;
public AclEditorFrame(final ClientModel model, final CmisObject object) {
super();
this.model = model;
this.object = object;
// get users
List<String> princiaplList = new ArrayList<String>();
try {
princiaplList.add("");
princiaplList.add("cmis:user");
String user = model.getClientSession().getSessionParameters().get(SessionParameter.USER);
if (user != null && user.length() > 0) {
princiaplList.add(user);
}
String anonymous = model.getRepositoryInfo().getPrincipalIdAnonymous();
if (anonymous != null && anonymous.length() > 0) {
princiaplList.add(anonymous);
}
String anyone = model.getRepositoryInfo().getPrincipalIdAnyone();
if (anyone != null && anyone.length() > 0) {
princiaplList.add(anyone);
}
if (object.getAcl() != null && object.getAcl().getAces() != null) {
List<String> aclPrinciaplList = new ArrayList<String>();
for (Ace ace : object.getAcl().getAces()) {
String pid = ace.getPrincipalId();
if (!princiaplList.contains(pid) && !aclPrinciaplList.contains(pid)) {
aclPrinciaplList.add(pid);
}
}
Collections.sort(aclPrinciaplList);
princiaplList.addAll(aclPrinciaplList);
}
} catch (Exception ex) {
princiaplList = new ArrayList<String>();
princiaplList.add("");
princiaplList.add("cmis:user");
}
// get permissions
List<String> permissionsList = new ArrayList<String>();
try {
permissionsList.add("");
for (PermissionDefinition pd : model.getRepositoryInfo().getAclCapabilities().getPermissions()) {
permissionsList.add(pd.getId());
}
} catch (Exception ex) {
permissionsList = new ArrayList<String>();
permissionsList.add("");
permissionsList.add("cmis:read");
permissionsList.add("cmis:write");
permissionsList.add("cmis:all");
}
addAceList = new AceList(princiaplList, permissionsList);
removeAceList = new AceList(princiaplList, permissionsList);
createGUI();
}
private void createGUI() {
setTitle(WINDOW_TITLE);
setPreferredSize(new Dimension(800, 600));
setMinimumSize(new Dimension(300, 120));
setLayout(new BorderLayout());
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
final Font labelFont = UIManager.getFont("Label.font");
final Font boldFont = labelFont.deriveFont(Font.BOLD, labelFont.getSize2D() * 1.2f);
final JPanel topPanel = new JPanel();
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
topPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JLabel nameLabel = new JLabel(object.getName());
nameLabel.setFont(boldFont);
topPanel.add(nameLabel);
topPanel.add(new JLabel(object.getId()));
add(topPanel, BorderLayout.PAGE_START);
// ACE panels
final JPanel addAcePanel = createAceListPanel("Add ACEs", addAceList);
final JPanel removeAcePanel = createAceListPanel("Remove ACEs", removeAceList);
JPanel centerPanel = new JPanel(new BorderLayout());
final JSplitPane aceSplitPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(addAcePanel),
new JScrollPane(removeAcePanel));
centerPanel.add(aceSplitPanel, BorderLayout.CENTER);
// propagation buttons
propagationRepositoryButton = new JRadioButton("repository determined", true);
propagationObjectOnlyButton = new JRadioButton("object only", false);
propagationPropagteButton = new JRadioButton("propagate", false);
try {
if (model.getRepositoryInfo().getAclCapabilities().getAclPropagation() == AclPropagation.OBJECTONLY) {
propagationPropagteButton.setEnabled(false);
}
} catch (Exception e) {
propagationPropagteButton.setEnabled(true);
}
ButtonGroup propagtionGroup = new ButtonGroup();
propagtionGroup.add(propagationRepositoryButton);
propagtionGroup.add(propagationObjectOnlyButton);
propagtionGroup.add(propagationPropagteButton);
JPanel propagtionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
propagtionPanel.add(new JLabel("ACL Propagation:"));
propagtionPanel.add(propagationRepositoryButton);
propagtionPanel.add(propagationObjectOnlyButton);
propagtionPanel.add(propagationPropagteButton);
centerPanel.add(propagtionPanel, BorderLayout.PAGE_END);
add(centerPanel, BorderLayout.CENTER);
// update button
JButton updateButton = new JButton("Update");
updateButton.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
updateButton.setDefaultCapable(true);
updateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (doApply()) {
dispose();
}
}
});
add(updateButton, BorderLayout.PAGE_END);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
aceSplitPanel.setDividerLocation(0.5f);
}
private JPanel createAceListPanel(final String title, final AceList list) {
final Font labelFont = UIManager.getFont("Label.font");
final Font boldFont = labelFont.deriveFont(Font.BOLD, labelFont.getSize2D() * 1.2f);
final JPanel result = new JPanel();
result.setLayout(new BoxLayout(result, BoxLayout.PAGE_AXIS));
final JPanel topPanel = new JPanel();
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.LINE_AXIS));
topPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JLabel titleLabel = new JLabel(title);
titleLabel.setFont(boldFont);
topPanel.add(titleLabel, BorderLayout.LINE_START);
topPanel.add(Box.createHorizontalGlue());
final JButton addButton = new JButton(ICON_ADD);
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
list.addNewAce();
}
});
topPanel.add(addButton, BorderLayout.LINE_END);
result.add(topPanel);
result.add(list);
return result;
}
/**
* Applies the ACEs.
*/
private boolean doApply() {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
List<Ace> adds = addAceList.getAces();
List<Ace> removes = removeAceList.getAces();
if (adds != null || removes != null) {
AclPropagation aclPropagation = AclPropagation.REPOSITORYDETERMINED;
if (propagationObjectOnlyButton.isSelected()) {
aclPropagation = AclPropagation.OBJECTONLY;
}
if (propagationPropagteButton.isSelected()) {
aclPropagation = AclPropagation.PROPAGATE;
}
object.applyAcl(adds, removes, aclPropagation);
model.reloadObject();
}
return true;
} catch (Exception ex) {
ClientHelper.showError(this, ex);
return false;
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
/**
* ACE list panel.
*/
private static class AceList extends JPanel {
private static final long serialVersionUID = 1L;
private final List<AceInputPanel> panels;
private final List<String> principals;
private final List<String> permissions;
public AceList(final List<String> principals, final List<String> permissions) {
super();
panels = new ArrayList<AceInputPanel>();
this.principals = principals;
this.permissions = permissions;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
}
public synchronized void addNewAce() {
AceInputPanel acePanel = new AceInputPanel(this, principals, permissions, panels.size());
panels.add(acePanel);
add(acePanel);
}
public synchronized void removeAce(int position) {
panels.remove(position);
for (int i = position; i < panels.size(); i++) {
panels.get(i).updatePosition(i);
}
removeAll();
for (AceInputPanel p : panels) {
add(p);
}
revalidate();
}
public synchronized List<Ace> getAces() {
List<Ace> result = new ArrayList<Ace>();
for (AceInputPanel p : panels) {
result.add(p.getAce());
}
return result.isEmpty() ? null : result;
}
}
/**
* ACE input panel.
*/
public static class AceInputPanel extends JPanel {
private static final long serialVersionUID = 1L;
private static final Color BACKGROUND1 = UIManager.getColor("Table:\"Table.cellRenderer\".background");
private static final Color BACKGROUND2 = UIManager.getColor("Table.alternateRowColor");
private static final Color LINE = new Color(0xB8, 0xB8, 0xB8);
private static final ImageIcon ICON_REMOVE = ClientHelper.getIcon("remove.png");
private final List<String> permissions;
private int position;
private final JComboBox principalBox;
private final JPanel permissionsPanel;
private final List<JComboBox> permissionBoxes;
public AceInputPanel(final AceList list, final List<String> principals, final List<String> permissions,
int position) {
super();
this.permissions = permissions;
updatePosition(position);
setLayout(new GridBagLayout());
setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, LINE),
BorderFactory.createEmptyBorder(10, 5, 10, 5)));
GridBagConstraints c = new GridBagConstraints();
c.gridheight = 1;
c.gridwidth = 1;
// col 1
c.gridx = 0;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LINE_START;
c.gridy = 0;
add(new JLabel("Principal:"), c);
c.gridy = 1;
add(new JSeparator(SwingConstants.HORIZONTAL), c);
c.gridy = 2;
add(new JLabel("Permissions:"), c);
// col 2
c.gridx = 1;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LINE_START;
principalBox = new JComboBox(principals.toArray(new String[0]));
principalBox.setEditable(true);
principalBox.setPrototypeDisplayValue("1234567890123456789012345");
c.gridy = 0;
add(principalBox, c);
c.gridy = 1;
add(new JSeparator(SwingConstants.HORIZONTAL), c);
permissionsPanel = new JPanel();
permissionsPanel.setLayout(new BoxLayout(permissionsPanel, BoxLayout.Y_AXIS));
permissionsPanel.setOpaque(false);
permissionBoxes = new ArrayList<JComboBox>();
updatePermissionsPanel(false);
c.gridy = 2;
add(permissionsPanel, c);
// col 3
c.gridx = 2;
c.weightx = 1;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_END;
c.gridy = 0;
JButton removeButton = new JButton(ICON_REMOVE);
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
list.removeAce(getPosition());
}
});
add(removeButton, c);
}
private JComboBox createPermissionBox() {
JComboBox result = new JComboBox(permissions.toArray(new String[0]));
result.setEditable(true);
result.setPrototypeDisplayValue("1234567890123456789012345");
JTextComponent editor = (JTextComponent) result.getEditor().getEditorComponent();
editor.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent event) {
updatePermissionsPanel(true);
}
});
editor.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB) {
updatePermissionsPanel(true);
}
}
});
return result;
}
private void updatePermissionsPanel(boolean focus) {
boolean changed = false;
if (!permissionBoxes.isEmpty()) {
int i = 0;
while (i < permissionBoxes.size() - 1) {
if (permissionBoxes.get(i).getSelectedItem().toString().trim().length() == 0) {
permissionBoxes.remove(i);
changed = true;
} else {
i++;
}
}
if (permissionBoxes.get(permissionBoxes.size() - 1).getSelectedItem().toString().trim().length() > 0) {
permissionBoxes.add(createPermissionBox());
changed = true;
}
} else {
permissionBoxes.add(createPermissionBox());
changed = true;
}
if (changed) {
permissionsPanel.removeAll();
for (JComboBox box : permissionBoxes) {
permissionsPanel.add(box);
}
revalidate();
if (focus) {
permissionBoxes.get(permissionBoxes.size() - 1).requestFocusInWindow();
}
}
}
private void updatePosition(int position) {
this.position = position;
setBackground(position % 2 == 0 ? BACKGROUND1 : BACKGROUND2);
}
public int getPosition() {
return position;
}
@Override
public Dimension getMaximumSize() {
return new Dimension(Short.MAX_VALUE, getPreferredSize().height);
}
public Ace getAce() {
List<String> permissionsList = new ArrayList<String>();
for (JComboBox box : permissionBoxes) {
String permission = box.getSelectedItem().toString().trim();
if (permission.length() > 0) {
permissionsList.add(permission);
}
}
return new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(principalBox.getSelectedItem()
.toString()), permissionsList);
}
}
}