Coverage Report - org.kuali.rice.kew.xml.GroupXmlParser
 
Classes in this File Line Coverage Branch Coverage Complexity
GroupXmlParser
0%
0/165
0%
0/80
9.571
 
 1  
 /*
 2  
  * Copyright 2007-2008 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kew.xml;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.InputStream;
 20  
 import java.util.ArrayList;
 21  
 import java.util.HashMap;
 22  
 import java.util.List;
 23  
 
 24  
 import javax.xml.parsers.ParserConfigurationException;
 25  
 
 26  
 import org.jdom.Document;
 27  
 import org.jdom.Element;
 28  
 import org.jdom.JDOMException;
 29  
 import org.kuali.rice.kew.exception.InvalidXmlException;
 30  
 import org.kuali.rice.kew.util.KEWConstants;
 31  
 import org.kuali.rice.kew.util.Utilities;
 32  
 import org.kuali.rice.kew.util.XmlHelper;
 33  
 import org.kuali.rice.kim.bo.Group;
 34  
 import org.kuali.rice.kim.bo.entity.KimPrincipal;
 35  
 import org.kuali.rice.kim.bo.group.dto.GroupInfo;
 36  
 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
 37  
 import org.kuali.rice.kim.bo.types.dto.KimTypeAttributeInfo;
 38  
 import org.kuali.rice.kim.bo.types.dto.KimTypeInfo;
 39  
 import org.kuali.rice.kim.service.IdentityManagementService;
 40  
 import org.kuali.rice.kim.service.KIMServiceLocator;
 41  
 import org.kuali.rice.kim.util.KimConstants;
 42  
 import org.xml.sax.SAXException;
 43  
 
 44  
 
 45  
 
 46  
 /**
 47  
  * Parses groups from XML.
 48  
  *
 49  
  * @see KimGroups
 50  
  *
 51  
  * @author Kuali Rice Team (rice.collab@kuali.org) *
 52  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 53  
  *
 54  
  */
 55  0
 public class GroupXmlParser implements XmlConstants {
 56  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(GroupXmlParser.class);
 57  
     private static final boolean DEFAULT_ACTIVE_VALUE = true;
 58  
     private static final String DEFAULT_GROUP_DESCRIPTION = "";
 59  0
     private HashMap<String, List<String>> memberGroupIds = new HashMap<String, List<String>>();
 60  0
     private HashMap<String, List<String>> memberGroupNames = new HashMap<String, List<String>>();
 61  0
     private HashMap<String, List<String>> memberPrincipalIds = new HashMap<String, List<String>>();
 62  0
     private AttributeSet groupAttributes = new AttributeSet();
 63  
 
 64  
     public List<GroupInfo> parseGroups(InputStream input) throws IOException, InvalidXmlException {
 65  
         try {
 66  0
             Document doc = XmlHelper.trimSAXXml(input);
 67  0
             Element root = doc.getRootElement();
 68  0
             return parseGroups(root);
 69  0
         } catch (JDOMException e) {
 70  0
             throw new InvalidXmlException("Parse error.", e);
 71  0
         } catch (SAXException e){
 72  0
             throw new InvalidXmlException("Parse error.",e);
 73  0
         } catch(ParserConfigurationException e){
 74  0
             throw new InvalidXmlException("Parse error.",e);
 75  
         }
 76  
     }
 77  
 
 78  
 
 79  
     /**
 80  
      * Parses and saves groups
 81  
      * @param element top-level 'data' element which should contain a <groups> child element
 82  
      * @return a list of parsed and saved, current, groups;
 83  
      * @throws InvalidXmlException
 84  
      */
 85  
     @SuppressWarnings("unchecked")
 86  
         public List<GroupInfo> parseGroups(Element element) throws InvalidXmlException {
 87  0
         List<GroupInfo> groupInfos = new ArrayList<GroupInfo>();
 88  0
         for (Element groupsElement: (List<Element>) element.getChildren(GROUPS, GROUP_NAMESPACE)) {
 89  
 
 90  0
             for (Element groupElement: (List<Element>) groupsElement.getChildren(GROUP, GROUP_NAMESPACE)) {
 91  0
                 groupInfos.add(parseGroup(groupElement));
 92  
             }
 93  
         }
 94  0
         for (GroupInfo groupInfo : groupInfos) {
 95  0
             IdentityManagementService identityManagementService = KIMServiceLocator.getIdentityManagementService();
 96  
 
 97  
             // check if group already exists
 98  0
             GroupInfo foundGroup = identityManagementService.getGroupByName(groupInfo.getNamespaceCode(), groupInfo.getGroupName());
 99  
 
 100  0
             if (foundGroup == null) {
 101  0
                 if ( LOG.isInfoEnabled() ) {
 102  0
                         LOG.info("Group named '" + groupInfo.getGroupName() + "' not found, creating new group named '" + groupInfo.getGroupName() + "'");
 103  
                 }
 104  
                 try {
 105  0
                     GroupInfo newGroupInfo =  identityManagementService.createGroup(groupInfo);
 106  
 
 107  0
                     String key = newGroupInfo.getNamespaceCode().trim() + KEWConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + newGroupInfo.getGroupName().trim();
 108  0
                     addGroupMembers(newGroupInfo, key);
 109  0
                 } catch (Exception e) {
 110  0
                     throw new RuntimeException("Error creating group with name '" + groupInfo.getGroupName() + "'", e);
 111  0
                 }
 112  
             } else {
 113  0
                     if ( LOG.isInfoEnabled() ) {
 114  0
                             LOG.info("Group named '" + groupInfo.getGroupName() + "' found, creating a new version");
 115  
                     }
 116  
                 try {
 117  0
                     groupInfo.setGroupId(foundGroup.getGroupId());
 118  0
                     identityManagementService.updateGroup(foundGroup.getGroupId(), groupInfo);
 119  
 
 120  
                     //delete existing group members and replace with new
 121  0
                     identityManagementService.removeAllGroupMembers(foundGroup.getGroupId());
 122  
 
 123  0
                     String key = groupInfo.getNamespaceCode().trim() + KEWConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + groupInfo.getGroupName().trim();
 124  0
                     addGroupMembers(groupInfo, key);
 125  
 
 126  0
                 } catch (Exception e) {
 127  0
                     throw new RuntimeException("Error updating group.", e);
 128  0
                 }
 129  
             }
 130  0
         }
 131  0
         return groupInfos;
 132  
     }
 133  
 
 134  
     @SuppressWarnings("unchecked")
 135  
         private GroupInfo parseGroup(Element element) throws InvalidXmlException {
 136  0
         GroupInfo groupInfo = new GroupInfo();
 137  0
         IdentityManagementService identityManagementService = KIMServiceLocator.getIdentityManagementService();
 138  0
         groupInfo.setGroupName(element.getChildText(NAME, GROUP_NAMESPACE));
 139  
 
 140  0
         if (groupInfo.getGroupName() == null) {
 141  0
             throw new InvalidXmlException("Group must have a name.");
 142  
         }
 143  
 
 144  0
         String groupNamespace = element.getChildText(NAMESPACE, GROUP_NAMESPACE);
 145  0
         if (groupNamespace != null) {
 146  0
             groupInfo.setNamespaceCode(groupNamespace.trim());
 147  
         } else {
 148  0
             throw new InvalidXmlException("Namespace must have a value.");
 149  
         }
 150  
 
 151  0
         String id = element.getChildText(ID, GROUP_NAMESPACE);
 152  0
         if (id != null) {
 153  0
             groupInfo.setGroupId(id.trim());
 154  
         }
 155  
 
 156  0
         String description = element.getChildText(DESCRIPTION, GROUP_NAMESPACE);
 157  0
         if (description != null && !description.trim().equals("")) {
 158  0
             groupInfo.setGroupDescription(description);
 159  
         }
 160  
 
 161  
         // Type element and children (namespace and name)
 162  0
         String typeId = null;
 163  0
         List<KimTypeAttributeInfo> kimTypeAttributes = new ArrayList<KimTypeAttributeInfo>();
 164  0
         if (element.getChild(TYPE, GROUP_NAMESPACE) != null) {
 165  0
             Element typeElement = element.getChild(TYPE, GROUP_NAMESPACE);
 166  0
             String typeNamespace = typeElement.getChildText(NAMESPACE, GROUP_NAMESPACE);
 167  0
             String typeName = typeElement.getChildText(NAME, GROUP_NAMESPACE);
 168  0
             KimTypeInfo kimTypeInfo = KIMServiceLocator.getTypeInfoService().getKimTypeByName(typeNamespace, typeName);
 169  0
             if (kimTypeInfo != null) {
 170  0
                     typeId = kimTypeInfo.getKimTypeId();
 171  0
                 kimTypeAttributes = kimTypeInfo.getAttributeDefinitions();
 172  
             } else  {
 173  0
                 throw new InvalidXmlException("Invalid type name and namespace specified.");
 174  
             }
 175  0
         } else { //set to default type
 176  0
             KimTypeInfo kimTypeDefault = KIMServiceLocator.getTypeInfoService().getKimTypeByName(KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, KimConstants.KIM_TYPE_DEFAULT_NAME);
 177  0
             if (kimTypeDefault != null) {
 178  0
                     typeId = kimTypeDefault.getKimTypeId();
 179  0
                 kimTypeAttributes = kimTypeDefault.getAttributeDefinitions();
 180  
             } else {
 181  0
                     throw new RuntimeException("Failed to locate the 'Default' group type!  Please ensure that it's in your database.");
 182  
             }
 183  
         }
 184  0
         groupInfo.setKimTypeId(typeId);
 185  
 
 186  
         //Active Indicator
 187  0
         groupInfo.setActive(DEFAULT_ACTIVE_VALUE);
 188  0
         if (element.getChildText(ACTIVE, GROUP_NAMESPACE) != null) {
 189  0
             String active = element.getChildText(ACTIVE, GROUP_NAMESPACE).trim();
 190  0
             if (active.toUpperCase().equals("N") || active.toUpperCase().equals("FALSE")) {
 191  0
                 groupInfo.setActive(false);
 192  
             }
 193  
         }
 194  
 
 195  
         //Get list of attribute keys
 196  0
         List<String> validAttributeKeys = new ArrayList<String>();
 197  0
         for (KimTypeAttributeInfo attribute : kimTypeAttributes) {
 198  0
             validAttributeKeys.add(attribute.getAttributeName());
 199  
         }
 200  
         //Group attributes
 201  0
         if (element.getChild(ATTRIBUTES, GROUP_NAMESPACE) != null) {
 202  0
             List<Element> attributes = element.getChild(ATTRIBUTES, GROUP_NAMESPACE).getChildren();
 203  0
             AttributeSet attributeSet = new AttributeSet();
 204  0
             for (Element attr : attributes ) {
 205  0
                 String key = attr.getAttributeValue(KEY);
 206  0
                 String value = attr.getAttributeValue(VALUE);
 207  0
                 attributeSet.put(key, value);
 208  0
                 if (!validAttributeKeys.contains(key)) {
 209  0
                     throw new InvalidXmlException("Invalid attribute specified.");
 210  
                 }
 211  0
             }
 212  0
             if (attributeSet.size() > 0) {
 213  0
                 groupInfo.setAttributes(attributeSet);
 214  
             }
 215  
         }
 216  
 
 217  
         //Group members
 218  
 
 219  0
         List<Element> members = element.getChild(MEMBERS, GROUP_NAMESPACE).getChildren();
 220  0
         for (Element member : members) {
 221  0
             String elementName = member.getName().trim();
 222  0
             if (elementName.equals(PRINCIPAL_NAME)) {
 223  0
                 String principalName = member.getText().trim();
 224  0
                 KimPrincipal principal = identityManagementService.getPrincipalByPrincipalName(principalName);
 225  0
                 if (principal != null) {
 226  0
                     addPrincipalToGroup(groupInfo.getNamespaceCode(), groupInfo.getGroupName(), principal.getPrincipalId());
 227  
                 } else {
 228  0
                     throw new InvalidXmlException("Principal Name "+principalName+" cannot be found.");
 229  
                 }
 230  0
             } else if (elementName.equals(PRINCIPAL_ID)) {
 231  0
                 String xmlPrincipalId = member.getText().trim();
 232  0
                 KimPrincipal principal = identityManagementService.getPrincipal(xmlPrincipalId);
 233  0
                 if (principal != null) {
 234  0
                     addPrincipalToGroup(groupInfo.getNamespaceCode(), groupInfo.getGroupName(), principal.getPrincipalId());
 235  
                 } else {
 236  0
                     throw new InvalidXmlException("Principal Id "+xmlPrincipalId+" cannot be found.");
 237  
                 }
 238  
             // Groups are handled differently since the member group may not be saved yet.  Therefore they need to be validated after the groups are saved.
 239  0
             } else if (elementName.equals(GROUP_ID)) {
 240  0
                 String xmlGroupId = member.getText().trim();
 241  0
                 addGroupToGroup(groupInfo.getNamespaceCode(), groupInfo.getGroupName(), xmlGroupId);
 242  0
             } else if (elementName.equals(GROUP_NAME)) {
 243  0
                 String xmlGroupName = member.getChildText(NAME, GROUP_NAMESPACE).trim();
 244  0
                 String xmlGroupNamespace = member.getChildText(NAMESPACE, GROUP_NAMESPACE).trim();
 245  0
                 addGroupNameToGroup(groupInfo.getNamespaceCode(), groupInfo.getGroupName(), xmlGroupNamespace, xmlGroupName);
 246  0
             } else {
 247  0
                 LOG.error("Unknown member element: " + elementName);
 248  
             }
 249  
 
 250  
 
 251  0
         }
 252  
 
 253  0
         return groupInfo;
 254  
 
 255  
     }
 256  
 
 257  
     private void addPrincipalToGroup(String groupNamespace, String groupName, String principalId) {
 258  0
         String key = groupNamespace.trim() + KEWConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + groupName.trim();
 259  0
         List<String> principalIds = memberPrincipalIds.get(key);
 260  0
         if (principalIds == null) {
 261  0
             principalIds = new ArrayList<String>();
 262  
         }
 263  0
         principalIds.add(principalId);
 264  0
         memberPrincipalIds.put(key, principalIds);
 265  0
     }
 266  
 
 267  
     private void addGroupToGroup(String groupNamespace, String groupName, String groupId) {
 268  0
         String key = groupNamespace.trim() + KEWConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + groupName.trim();
 269  0
         List<String> groupIds = memberGroupIds.get(key);
 270  0
         if (groupIds == null) {
 271  0
             groupIds = new ArrayList<String>();
 272  
         }
 273  0
         groupIds.add(groupId);
 274  0
         memberGroupIds.put(key, groupIds);
 275  0
     }
 276  
 
 277  
     private void addGroupNameToGroup(String groupNamespace, String groupName, String memberGroupNamespace, String memberGroupName) {
 278  0
         String key = groupNamespace.trim() + KEWConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + groupName.trim();
 279  0
         List<String> groupNames = memberGroupNames.get(key);
 280  0
         if (groupNames == null) {
 281  0
             groupNames = new ArrayList<String>();
 282  
         }
 283  0
         groupNames.add(memberGroupNamespace.trim() + KEWConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + memberGroupName.trim());
 284  0
         memberGroupNames.put(key, groupNames);
 285  0
     }
 286  
 
 287  
     private void addGroupMembers(GroupInfo groupInfo, String key) throws InvalidXmlException {
 288  0
         IdentityManagementService identityManagementService = KIMServiceLocator.getIdentityManagementService();
 289  0
         List<String> groupIds = memberGroupIds.get(key);
 290  0
         if (groupIds != null) {
 291  0
             for (String groupId : groupIds) {
 292  0
                 Group group = identityManagementService.getGroup(groupId);
 293  0
                 if (group != null) {
 294  0
                     identityManagementService.addGroupToGroup(group.getGroupId(), groupInfo.getGroupId());
 295  
                 } else {
 296  0
                     throw new InvalidXmlException("Group Id "+groupId+" cannot be found.");
 297  
                 }
 298  0
             }
 299  
         }
 300  0
         List<String> groupNames = memberGroupNames.get(key);
 301  0
         if (groupNames != null) {
 302  0
             for (String groupName : groupNames) {
 303  0
                 Group group = identityManagementService.getGroupByName(Utilities.parseGroupNamespaceCode(groupName), Utilities.parseGroupName(groupName));
 304  0
                 if (group != null) {
 305  0
                         identityManagementService.addGroupToGroup(group.getGroupId(), groupInfo.getGroupId());
 306  
                 } else {
 307  0
                     throw new InvalidXmlException("Group "+groupName+" cannot be found.");
 308  
                 }
 309  0
             }
 310  
         }
 311  0
         List<String> principalIds = memberPrincipalIds.get(key);
 312  0
         if (principalIds != null) {
 313  0
             for (String principalId : principalIds) {
 314  0
                     identityManagementService.addPrincipalToGroup(principalId, groupInfo.getGroupId());
 315  
             }
 316  
         }
 317  
 
 318  0
     }
 319  
 }