components/visual-panels/usermgr/src/java/vpanels/app/usermgr/com/oracle/solaris/vp/panels/usermgr/client/swing/AuthRightsPanel.java
17510631 Backport 16984138 to 11.2 - vp components must change to match RAD2 enhancements
17548766 Backport 16808665 to 11.2 - User Manager Panel can assign profiles, but not auth
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
*/
package com.oracle.solaris.vp.panels.usermgr.client.swing;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import com.oracle.solaris.vp.util.misc.finder.Finder;
/**
* SMC code adapted for Visual Panels
*
* Rights Profiles Panel for Rights Settings
*/
public class AuthRightsPanel extends JPanel {
public static Arranger profPanel;
private static DblTreeNode srcRoot;
private static DblTreeNode dstRoot;
private DefaultTreeModel srcModel, dstModel;
private DblTreeNode [] profNodes;
private ProfTreeNode [] profTreeNodes;
private ProfTreeNode currProfTreeNode;
private DblTreeNode currDblTreeNode;
private String targetRightName;
private String targetRight;
private JPanel securityPanel;
private UserManagedObject userObj = null;
private UserMgrPanelDescriptor panelDesc = null;
private Vector vAllRightObjs = null;
private boolean isProfListOK = true;
/**
* Constructs a panel to contain supplementary rights properties for
* the right object.
*/
public AuthRightsPanel(UserMgrPanelDescriptor panelDesc,
UserManagedObject userObj) {
super();
this.panelDesc = panelDesc;
this.userObj = userObj;
createGui();
loadProfiles();
} // constructor
/**
* Method for creating GUI
*/
private void createGui() {
// Set the panel layout
GridBagConstraints gbc = new GridBagConstraints();
this.setLayout(new GridBagLayout());
// Excluded and Included rights panel
securityPanel = null;
profPanel = new Arranger("usermgr.advanced.auth_rights.available",
"usermgr.advanced.auth_rights.granted");
Dimension dimension = new Dimension(200, 300);
profPanel.srcTree.setCellRenderer(new ProfileRenderer(this));
profPanel.srcTree.setVisibleRowCount(10);
profPanel.srcTree.setSize(dimension);
profPanel.dstTree.setCellRenderer(new ProfileRenderer(this));
profPanel.dstTree.setVisibleRowCount(10);
profPanel.dstTree.setSize(dimension);
Constraints.constrain(this, profPanel,
0, 0, 1, 1,
gbc.BOTH, gbc.CENTER,
1.0, 1.0, 10, 10, 10, 10);
} // end createGui
/**
* Load the Source and Destination trees for rights excluded and
* included lists.
*/
private void loadProfiles() {
// Reset the data models. So old data is discarded
profPanel.resetModels();
// Initialize the excluded rights list with all profiles
// except for the current one, since a profile can not be
// assigned to itself. Note that all profiles are created
// as top-level profiles.
vAllRightObjs = getAvailableProfs();
srcModel = (DefaultTreeModel) profPanel.srcTree.getModel();
srcRoot = (DblTreeNode) srcModel.getRoot();
dstModel = (DefaultTreeModel) profPanel.dstTree.getModel();
dstRoot = (DblTreeNode) dstModel.getRoot();
profNodes = new DblTreeNode[vAllRightObjs.size()];
profTreeNodes = new ProfTreeNode[vAllRightObjs.size()];
int n = 0;
Enumeration e = vAllRightObjs.elements();
// Build an array of tree nodes that can be used for sorting.
while (e.hasMoreElements()) {
String rightObj = (String)e.nextElement();
String rightName = rightObj;
profTreeNodes[n] = new ProfTreeNode(rightObj);
n++;
}
// Sort the list of ProfTreeNode objects.
if (profTreeNodes.length > 1) {
NodeCompare comp = new NodeCompare();
Sort.sort(profTreeNodes, comp);
}
// With the sorted tree nodes, now we build the src tree.
for (int i = 0; i < profTreeNodes.length; i++) {
profNodes[i] = new DblTreeNode((Object)profTreeNodes[i]);
srcModel.insertNodeInto(profNodes[i], srcRoot, i);
TreePath nodepath = new TreePath(profNodes[i].getPath());
// Make initial display of excluded list
profPanel.srcTree.scrollPathToVisible(nodepath);
}
// Set TreeModel listeners
srcModel.addTreeModelListener(new TreeModelListener() {
public void treeNodesInserted(TreeModelEvent e) {
enableProfileChoices(e);
}
public void treeNodesRemoved(TreeModelEvent e) {
disableProfileChoices(e);
}
public void treeNodesChanged(TreeModelEvent e) {}
public void treeStructureChanged(TreeModelEvent e) {}
});
dstModel.addTreeModelListener(new TreeModelListener() {
public void treeNodesInserted(TreeModelEvent e) {
updateDstTree(e);
}
public void treeNodesRemoved(TreeModelEvent e) {
updateDstTree(e);
}
public void treeNodesChanged(TreeModelEvent e) {}
public void treeStructureChanged(TreeModelEvent e) {}
});
// Build subprofiles recursively
for (int i = 0; i < profNodes.length; i++) {
rebuildSubProfiles(profNodes[i], profNodes[i]);
}
String [] subProfList = null;
// Get the list of profiles that are assigned to current user/role
// (in user_attr entry).
String rights = userObj.getAuthRights();
if (rights != null) {
subProfList = userObj.getAuthRights().split(",");
}
profPanel.setInitSelection();
if (rights == null || subProfList == null) {
return;
}
// Move subprofiles of current profile from excluded list
// to included list.
// Note that a dimmed profile will stay dimmed after the move.
// Therefore, a user can not "unassign" a dimmed profile on the
// included list.
for (int j = 0; j < subProfList.length; j++) {
boolean foundSubProf = false;
int count = 0;
for (int i = 0; i < profNodes.length; i++) {
String profString = profNodes[i].toString();
if (profString.equals(subProfList[j])) {
foundSubProf = true;
count = i;
break;
}
}
if (foundSubProf) {
profPanel.initLeaf(profPanel.srcTree,
profPanel.dstTree, profNodes[count]);
}
}
profPanel.setInitSelection();
} // end loadProfiles
private void updateDstTree(TreeModelEvent e) {
Vector<DblTreeNode> inclProfsVec = new Vector<DblTreeNode>();
Enumeration inclProfsEnum = dstRoot.breadthFirstEnumeration();
while (inclProfsEnum.hasMoreElements()) {
DblTreeNode node = (DblTreeNode)inclProfsEnum.nextElement();
inclProfsVec.addElement(node);
node.setConflict(false);
}
// Maintain included names as array as optimization
DblTreeNode [] inclProfs = new DblTreeNode[inclProfsVec.size()];
inclProfsVec.copyInto(inclProfs);
if (inclProfs.length < 2)
return;
for (int i = 0; i < inclProfs.length; i++) {
String testString = inclProfs[i].toString();
for (int j = i + 1; j < inclProfs.length; j++) {
if (testString.equals(inclProfs[j].toString())) {
inclProfs[j].setConflict(true);
inclProfs[i].setConflict(true);
TreeNode [] nodes = inclProfs[j].getPath();
DblTreeNode parentProf = (DblTreeNode)nodes[1];
parentProf.setConflict(true);
}
}
}
} // end updateDstTree
private void enableProfileChoices(TreeModelEvent e) {
// Get names of currently included profiles
if (e.getPath().length > 1)
return;
Vector<String> inclProfsVec = new Vector<String>();
Enumeration inclProfs = dstRoot.depthFirstEnumeration();
while (inclProfs.hasMoreElements()) {
inclProfsVec.addElement(inclProfs.nextElement().toString());
}
// Maintain included names as array as optimization
String [] inclProfNames = new String[inclProfsVec.size()];
inclProfsVec.copyInto(inclProfNames);
// Look for excluded list items needing updating
Enumeration topProfs = srcRoot.children();
while (topProfs.hasMoreElements()) {
DblTreeNode nextTop = (DblTreeNode)topProfs.nextElement();
boolean matchFound = false;
Enumeration exclProfs = nextTop.depthFirstEnumeration();
while (exclProfs.hasMoreElements()) {
String testString = exclProfs.nextElement().toString();
for (int i = 0; i < inclProfNames.length; i++) {
if (testString.equals(inclProfNames[i])) {
matchFound = true;
break;
}
}
if (matchFound)
break;
}
// A Profile hierarchy needs to be enabled
if (!matchFound) {
exclProfs = nextTop.depthFirstEnumeration();
while (exclProfs.hasMoreElements()) {
DblTreeNode onNode =
(DblTreeNode) exclProfs.nextElement();
onNode.setConflict(false);
}
nextTop.setConflict(false);
}
}
} // end enableProfileChoices
private void disableProfileChoices(TreeModelEvent e) {
if (e.getPath().length > 1)
return;
Object[] children = e.getChildren();
DblTreeNode node = (DblTreeNode)children[0];
Enumeration kids = node.breadthFirstEnumeration();
while (kids.hasMoreElements()) {
disableRecursively((DblTreeNode)kids.nextElement());
}
} // end disableProfileChoices
private void disableRecursively(DblTreeNode node) {
String testString = node.toString();
Enumeration exclProfs = srcRoot.breadthFirstEnumeration();
while (exclProfs.hasMoreElements()) {
DblTreeNode exclNode = (DblTreeNode)exclProfs.nextElement();
if (testString.equals(exclNode.toString())) {
TreeNode [] nodes = exclNode.getPath();
DblTreeNode parentProf = (DblTreeNode)nodes[1];
if (!parentProf.isConflict()) {
parentProf.setConflict(true);
exclNode.setConflict(true);
}
}
}
} // end disableRecursively
private void rebuildSubProfiles(DblTreeNode profNode, DblTreeNode topNode) {
// First unlink the old children
int childCount = profNode.getChildCount();
for (int i = 0; i < childCount; i++) {
DblTreeNode child = (DblTreeNode) srcModel.getChild(profNode, 0);
srcModel.removeNodeFromParent(child);
}
// Then recursively construct new nodes for all the children
DblTreeNode childNode;
int i = 0;
Enumeration topList = topNode.breadthFirstEnumeration();
// Find sub-profile list in RightObj of cached tree node
ProfTreeNode pTreeNode = (ProfTreeNode)profNode.getUserObject();
String rObj = pTreeNode.getRightObj();
// ProfAttrObj targetProfAttr = rObj.getProfAttr();
String [] profList = null; // targetProfAttr.getProfNames();
if (profList == null)
return;
for (int k = 0; k < profList.length; k++) {
String name = profList[k];
// Prevent infinite recursive loops
boolean cyclic = false;
while (topList.hasMoreElements()) {
if (name.equals(topList.nextElement().toString())) {
cyclic = true;
// Mark the parent as cyclic
topNode.setCyclic(true);
Enumeration dupNodes = topNode.breadthFirstEnumeration();
while (dupNodes.hasMoreElements()) {
childNode = (DblTreeNode)dupNodes.nextElement();
if (name.equals(childNode.toString())) {
childNode.setCyclic(true);
}
}
break;
}
}
for (int j = 0; j < profTreeNodes.length; j++) {
if (name.equals(profTreeNodes[j].toString())) {
childNode = new DblTreeNode((Object)profTreeNodes[j]);
srcModel.insertNodeInto(childNode, profNode, i++);
childNode.setEnabled(false);
if (cyclic)
childNode.setCyclic(true);
else
rebuildSubProfiles(childNode, topNode);
}
}
}
} // end rebuildSubProfiles
public String updateRightSubProps(String rightObj) {
if (isProfListOK) {
Vector<String> vAssignedProfs = new Vector<String>();
// Get the first generation children that are assigned to
// current profile.
DblTreeNode root = (DblTreeNode)dstModel.getRoot();
Enumeration kids;
kids = root.children();
while (kids.hasMoreElements()) {
DblTreeNode childNode;
childNode = (DblTreeNode)kids.nextElement();
vAssignedProfs.addElement(childNode.toString());
}
// ProfAttrObj profAttr = rightObj.getProfAttr();
// profAttr.setProfNamesVector(vAssignedProfs);
}
return (rightObj);
} // end updateRightSubProps
public Vector<String> getAssignedProfs() {
Vector<String> vAssignedProfs = new Vector<String>();
if (!isProfListOK) {
return vAssignedProfs;
}
// Get the first generation children that are assigned to
// current profile.
DblTreeNode root = (DblTreeNode)dstModel.getRoot();
Enumeration kids;
kids = root.children();
while (kids.hasMoreElements()) {
DblTreeNode childNode;
childNode = (DblTreeNode)kids.nextElement();
vAssignedProfs.addElement(childNode.toString());
}
return vAssignedProfs;
}
private Vector<String> getAvailableProfs() {
Vector<String> rights = new Vector<String>();
for (String s : panelDesc.getProfiles()) {
rights.add(s);
}
return (rights);
}
public void setUser(UserManagedObject userObj) {
this.userObj = userObj;
loadProfiles();
}
public UserManagedObject updateUser() {
Vector<String> vProfs = getAssignedProfs();
String profStr;
if (vProfs.size() > 0) {
profStr = vProfs.elementAt(0);
} else {
profStr = "";
}
for (int i = 1; i < vProfs.size(); i++) {
profStr = profStr.concat(",");
profStr = profStr.concat(vProfs.elementAt(i));
}
userObj.getAuthRightsProperty().setValue(profStr);
return (userObj);
}
class ProfileRenderer extends DefaultTreeCellRenderer {
private boolean selected;
Icon warningIcon;
AuthRightsPanel rightsPanel;
public ProfileRenderer(AuthRightsPanel rightsPanel) {
this.rightsPanel = rightsPanel;
setClosedIcon(null);
setOpenIcon(null);
setLeafIcon(null);
warningIcon = Finder.getIcon("images/warning.gif");
}
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
FocusEvent e = null;
this.selected = selected;
DefaultTreeCellRenderer cr =
(DefaultTreeCellRenderer)tree.getCellRenderer();
cr.setLeafIcon(null);
DblTreeNode node = (DblTreeNode)value;
if (node.getParent() == null) {
// maybe the same as row == 0
setText(node.toString());
} else if (node.getUserObject() instanceof ProfTreeNode) {
ProfTreeNode profsdef = (ProfTreeNode)node.getUserObject();
setText(profsdef.toString());
// setIcon(actionIcon);
if (node.isConflict())
if (tree == rightsPanel.profPanel.dstTree)
cr.setLeafIcon(warningIcon);
}
super.getTreeCellRendererComponent(tree, value, selected, expanded,
leaf, row, hasFocus);
return this;
} // end getTreeCellRendererComponent
}
class ProfTreeNode {
String name;
String rightObj = null;
public ProfTreeNode(String rightObj) {
this.rightObj = rightObj;
this.name = rightObj;
}
public String getRightObj() {
return rightObj;
}
public String toString() {
return name;
}
}
class NodeCompare implements Compare {
/**
* The compare method compares two ProfTreeNode objects by comparing
* their profile names. The parameters are specified as Object class
* objects for QuickSort.
*
* @param a The first Node.
* @param b The second Node.
*
*/
public final int doCompare(Object a, Object b) {
ProfTreeNode e1, e2;
String e1Name, e2Name;
e1 = (ProfTreeNode)a;
e2 = (ProfTreeNode)b;
e1Name = e1.toString();
e2Name = e2.toString();
return (e1Name.compareTo(e2Name));
}
}
}