Author: thomas.heute(a)jboss.com
Date: 2010-11-25 03:28:40 -0500 (Thu, 25 Nov 2010)
New Revision: 5262
Modified:
epp/portal/branches/EPP_5_1_Branch/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java
Log:
JBEPP-635: StackOverflowError if LDAP groups contain circular cross references
Modified:
epp/portal/branches/EPP_5_1_Branch/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java
===================================================================
---
epp/portal/branches/EPP_5_1_Branch/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java 2010-11-25
08:20:16 UTC (rev 5261)
+++
epp/portal/branches/EPP_5_1_Branch/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java 2010-11-25
08:28:40 UTC (rev 5262)
@@ -57,6 +57,8 @@
private PicketLinkIDMOrganizationServiceImpl orgService;
+ private static final String CYCLIC_ID =
"org.gatein.portal.identity.LOOPED_GROUP_ID";
+
public GroupDAOImpl(PicketLinkIDMOrganizationServiceImpl orgService,
PicketLinkIDMService service)
{
service_ = service;
@@ -557,7 +559,7 @@
}
// Resolve full ID
- String id = getGroupId(jbidGroup);
+ String id = getGroupId(jbidGroup, null);
exoGroup.setId(id);
@@ -575,13 +577,27 @@
return exoGroup;
}
- private String getGroupId(org.picketlink.idm.api.Group jbidGroup) throws Exception
+ /**
+ * Calculates group id by checking all parents up to the root group or group type
mapping from the configuration.
+ *
+ * @param jbidGroup
+ * @param processed
+ * @return
+ * @throws Exception
+ */
+ private String getGroupId(org.picketlink.idm.api.Group jbidGroup,
+ List<org.picketlink.idm.api.Group> processed) throws
Exception
{
if (jbidGroup.equals(getRootGroup()))
{
return "";
}
+ if (processed == null)
+ {
+ processed = new LinkedList<org.picketlink.idm.api.Group>();
+ }
+
Collection<org.picketlink.idm.api.Group> parents = new HashSet();
String gtnGroupName = getGtnGroupName(jbidGroup.getName());
@@ -596,7 +612,13 @@
log.info("Identity operation error: ", e);
}
-
+ // Check if there is cross reference so we ended in a loop and break the process.
+ if (parents.size() > 0 &&
processed.contains(parents.iterator().next()))
+ {
+ processed.remove(processed.size() - 1);
+ return CYCLIC_ID;
+ }
+ // If there are no parents or more then one parent
if (parents.size() == 0 || parents.size() > 1)
{
@@ -606,34 +628,64 @@
"defined by type mappings or just place it under root /");
}
+ return obtainMappedId(jbidGroup, gtnGroupName);
- String id =
orgService.getConfiguration().getParentId(jbidGroup.getGroupType());
+ }
+ processed.add(jbidGroup);
+ String parentGroupId =
getGroupId(((org.picketlink.idm.api.Group)parents.iterator().next()),processed);
-
- if (id != null &&
orgService.getConfiguration().isForceMembershipOfMappedTypes())
+ // Check if loop occured
+ if (parentGroupId.equals(CYCLIC_ID))
+ {
+ // if there are still processed groups in the list we are in nested call so
remove last one and go back
+ if (processed.size() > 0)
{
- if (id.endsWith("/*"))
- {
- id = id.substring(0, id.length() - 2);
- }
-
- return id + "/" + gtnGroupName;
+ processed.remove(processed.size() - 1);
+ return parentGroupId;
}
+ // if we finally reached the first group from the looped ones then just return
id calculated from
+ // mappings or connect it to the root
+ else
+ {
+ return obtainMappedId(jbidGroup, gtnGroupName);
+ }
+ }
- // All groups not connected to the root should be just below the root
- return "/" + gtnGroupName;
+ return parentGroupId + "/" + gtnGroupName;
- //TODO: make it configurable
- // throw new IllegalStateException("Group present that is not connected to
the root: " + jbidGroup.getName());
+ }
+ /**
+ * Obtain group id based on groupType mapping from configuration or if this fails just
place it under root /
+ *
+ * @param jbidGroup
+ * @param gtnGroupName
+ * @return
+ */
+ private String obtainMappedId(org.picketlink.idm.api.Group jbidGroup, String
gtnGroupName)
+ {
+ String id = orgService.getConfiguration().getParentId(jbidGroup.getGroupType());
+
+
+
+ if (id != null &&
orgService.getConfiguration().isForceMembershipOfMappedTypes())
+ {
+ if (id.endsWith("/*"))
+ {
+ id = id.substring(0, id.length() - 2);
+ }
+
+ return id + "/" + gtnGroupName;
}
- String parentGroupId =
getGroupId(((org.picketlink.idm.api.Group)parents.iterator().next()));
- return parentGroupId + "/" + gtnGroupName;
+ // All groups not connected to the root should be just below the root
+ return "/" + gtnGroupName;
+ //TODO: make it configurable
+ // throw new IllegalStateException("Group present that is not connected to the
root: " + jbidGroup.getName());
}
private org.picketlink.idm.api.Group persistGroup(Group exoGroup) throws Exception