diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AuthorityMigrationPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AuthorityMigrationPatch.java index ecc5d3a030..9877b268c8 100644 --- a/source/java/org/alfresco/repo/admin/patch/impl/AuthorityMigrationPatch.java +++ b/source/java/org/alfresco/repo/admin/patch/impl/AuthorityMigrationPatch.java @@ -212,6 +212,59 @@ public class AuthorityMigrationPatch extends AbstractPatch return assocCount; } + /** + * Truncates authority names so that they are within {@link QName#MAX_LENGTH} characters. + * + * @param authoritiesToCreate + * the original, untruncated authorities to create + * @param parentAssocs + * the original parent associations to create + * @param targetAuthoritiesToCreate + * the authorities to create with names shortened to QName.MAX_LENGTH + * @param targetParentAssocs + * the parent associations modified to match targetAuthoritiesToCreate + */ + private void truncateAuthorities(final Map authoritiesToCreate, + Map> parentAssocs, Map targetAuthoritiesToCreate, + Map> targetParentAssocs) + { + // Work through each authority, creating a unique truncated name where necessary and populating a map of old to + // new names + Map targetLookup = new TreeMap(); + for (Map.Entry entry : authoritiesToCreate.entrySet()) + { + String sourceName = entry.getKey(); + int sourceLength = sourceName.length(); + String targetName = sourceLength > QName.MAX_LENGTH ? sourceName.substring(0, QName.MAX_LENGTH) : sourceName; + int i=0; + while (targetAuthoritiesToCreate.containsKey(targetName)) + { + String suffix = String.valueOf(++i); + int prefixLength = QName.MAX_LENGTH - suffix.length(); + if (prefixLength < 0) + { + break; + } + targetName = (sourceLength > prefixLength ? sourceName.substring(0, prefixLength) : sourceName) + suffix; + } + targetLookup.put(sourceName, targetName); + targetAuthoritiesToCreate.put(targetName, entry.getValue()); + } + // Apply the name mapping to the parent associations + for (Map.Entry> entry: parentAssocs.entrySet()) + { + Set parents = new TreeSet(); + for (String parent : entry.getValue()) + { + String targetParent = targetLookup.get(parent); + parents.add(targetParent == null ? parent : targetParent); + } + String sourceChild = entry.getKey(); + String targetChild = targetLookup.get(sourceChild); + targetParentAssocs.put(targetChild == null ? sourceChild : targetChild, parents); + } + } + /** * Migrates the authorities and their associations. * @@ -358,19 +411,24 @@ public class AuthorityMigrationPatch extends AbstractPatch Map> parentAssocs = new TreeMap>(); assocs = retrieveAuthorities(null, authorityContainer, authoritiesToCreate, parentAssocs); + // Truncate names to an acceptable length + Map targetAuthoritiesToCreate = new TreeMap(); + Map> targetParentAssocs = new TreeMap>(); + truncateAuthorities(authoritiesToCreate, parentAssocs, targetAuthoritiesToCreate, targetParentAssocs); + // Sort the group associations in parent-first order (root groups first) Map> sortedParentAssocs = new LinkedHashMap>( parentAssocs.size() * 2); List authorityPath = new ArrayList(5); - for (String authority : parentAssocs.keySet()) + for (String authority : targetParentAssocs.keySet()) { authorityPath.add(authority); - visitGroupAssociations(authorityPath, parentAssocs, sortedParentAssocs); + visitGroupAssociations(authorityPath, targetParentAssocs, sortedParentAssocs); authorityPath.clear(); } // Recreate the authorities and their associations in parent-first order - migrateAuthorities(authoritiesToCreate, sortedParentAssocs); + migrateAuthorities(targetAuthoritiesToCreate, sortedParentAssocs); authorities = authoritiesToCreate.size(); } // build the result message