/* * 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 inclProfsVec = new Vector(); 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 inclProfsVec = new Vector(); 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 vAssignedProfs = new Vector(); // 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 getAssignedProfs() { Vector vAssignedProfs = new Vector(); 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 getAvailableProfs() { Vector rights = new Vector(); for (String s : panelDesc.getProfiles()) { rights.add(s); } return (rights); } public void setUser(UserManagedObject userObj) { this.userObj = userObj; loadProfiles(); } public UserManagedObject updateUser() { Vector 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)); } } }