List of usage examples for java.text DateFormat getDateTimeInstance
public static final DateFormat getDateTimeInstance()
From source file:op.care.values.PnlValues.java
private JPanel getMenu(final ResValue resValue) { final ResValueTypes vtype = resValue.getType(); JPanel pnlMenu = new JPanel(new VerticalLayout()); boolean doesNotBelongToResInfos = ResInfoTools.getInfosFor(resValue).isEmpty(); if (doesNotBelongToResInfos && OPDE.getAppInfo().isAllowedTo(InternalClassACL.UPDATE, internalClassID)) { /***/*from w ww . j a va2 s. c o m*/ * _____ _ _ _ * | ____|__| (_) |_ * | _| / _` | | __| * | |__| (_| | | |_ * |_____\__,_|_|\__| * */ final JButton btnEdit = GUITools.createHyperlinkButton("nursingrecords.vitalparameters.btnEdit.tooltip", SYSConst.icon22edit3, null); btnEdit.setAlignmentX(Component.RIGHT_ALIGNMENT); btnEdit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { new DlgValue(resValue.clone(), DlgValue.MODE_EDIT, new Closure() { @Override public void execute(Object o) { if (o != null) { EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); em.lock(em.merge(resident), LockModeType.OPTIMISTIC); final ResValue newValue = em.merge((ResValue) o); ResValue oldValue = em.merge(resValue); em.lock(oldValue, LockModeType.OPTIMISTIC); newValue.setReplacementFor(oldValue); for (SYSVAL2FILE oldAssignment : oldValue.getAttachedFilesConnections()) { em.remove(oldAssignment); } oldValue.getAttachedFilesConnections().clear(); for (SYSVAL2PROCESS oldAssignment : oldValue.getAttachedProcessConnections()) { em.remove(oldAssignment); } oldValue.getAttachedProcessConnections().clear(); oldValue.setEditedBy(em.merge(OPDE.getLogin().getUser())); oldValue.setEditDate(new Date()); oldValue.setReplacedBy(newValue); em.getTransaction().commit(); DateTime dt = new DateTime(newValue.getPit()); final String keyType = vtype.getID() + ".xtypes"; final String key = vtype.getID() + ".xtypes." + Integer.toString(dt.getYear()) + ".year"; synchronized (mapType2Values) { mapType2Values.get(key).remove(resValue); mapType2Values.get(key).add(oldValue); mapType2Values.get(key).add(newValue); Collections.sort(mapType2Values.get(key)); } createCP4Year(vtype, dt.getYear()); try { synchronized (cpMap) { cpMap.get(keyType).setCollapsed(false); cpMap.get(key).setCollapsed(false); } } catch (PropertyVetoException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } buildPanel(); } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } } }); } }); btnEdit.setEnabled(!resValue.isObsolete()); pnlMenu.add(btnEdit); /*** * ____ _ _ * | _ \ ___| | ___| |_ ___ * | | | |/ _ \ |/ _ \ __/ _ \ * | |_| | __/ | __/ || __/ * |____/ \___|_|\___|\__\___| * */ final JButton btnDelete = GUITools.createHyperlinkButton( "nursingrecords.vitalparameters.btnDelete.tooltip", SYSConst.icon22delete, null); btnDelete.setAlignmentX(Component.RIGHT_ALIGNMENT); btnDelete.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { new DlgYesNo(SYSTools.xx("misc.questions.delete1") + "<br/><i>" + DateFormat.getDateTimeInstance().format(resValue.getPit()) + "</i><br/>" + SYSTools.xx("misc.questions.delete2"), SYSConst.icon48delete, new Closure() { @Override public void execute(Object o) { if (o.equals(JOptionPane.YES_OPTION)) { EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); ResValue myValue = em.merge(resValue); myValue.setDeletedBy(em.merge(OPDE.getLogin().getUser())); for (SYSVAL2FILE file : myValue.getAttachedFilesConnections()) { em.remove(file); } myValue.getAttachedFilesConnections().clear(); // Vorgangszuordnungen entfernen for (SYSVAL2PROCESS connObj : myValue.getAttachedProcessConnections()) { em.remove(connObj); } myValue.getAttachedProcessConnections().clear(); myValue.getAttachedProcesses().clear(); em.getTransaction().commit(); DateTime dt = new DateTime(myValue.getPit()); final String keyType = vtype.getID() + ".xtypes"; final String key = vtype.getID() + ".xtypes." + Integer.toString(dt.getYear()) + ".year"; synchronized (mapType2Values) { mapType2Values.get(key).remove(resValue); mapType2Values.get(key).add(myValue); Collections.sort(mapType2Values.get(key)); } createCP4Year(vtype, dt.getYear()); try { synchronized (cpMap) { cpMap.get(keyType).setCollapsed(false); cpMap.get(key).setCollapsed(false); } } catch (PropertyVetoException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } buildPanel(); } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } } }); } }); btnDelete.setEnabled(!resValue.isObsolete()); pnlMenu.add(btnDelete); pnlMenu.add(new JSeparator()); /*** * _ _ _____ _ _ * | |__ | |_ _ __ | ___(_) | ___ ___ * | '_ \| __| '_ \| |_ | | |/ _ \/ __| * | |_) | |_| | | | _| | | | __/\__ \ * |_.__/ \__|_| |_|_| |_|_|\___||___/ * */ final JButton btnFiles = GUITools.createHyperlinkButton("misc.btnfiles.tooltip", SYSConst.icon22attach, null); btnFiles.setAlignmentX(Component.RIGHT_ALIGNMENT); btnFiles.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { new DlgFiles(resValue, new Closure() { @Override public void execute(Object o) { EntityManager em = OPDE.createEM(); final ResValue myValue = em.find(ResValue.class, resValue.getID()); em.close(); DateTime dt = new DateTime(myValue.getPit()); final String key = vtype.getID() + ".xtypes." + Integer.toString(dt.getYear()) + ".year"; synchronized (mapType2Values) { mapType2Values.get(key).remove(resValue); mapType2Values.get(key).add(myValue); Collections.sort(mapType2Values.get(key)); } buildPanel(); } }); } }); btnFiles.setEnabled(!resValue.isObsolete() && OPDE.isFTPworking()); pnlMenu.add(btnFiles); /*** * _ _ ____ * | |__ | |_ _ __ | _ \ _ __ ___ ___ ___ ___ ___ * | '_ \| __| '_ \| |_) | '__/ _ \ / __/ _ \/ __/ __| * | |_) | |_| | | | __/| | | (_) | (_| __/\__ \__ \ * |_.__/ \__|_| |_|_| |_| \___/ \___\___||___/___/ * */ final JButton btnProcess = GUITools.createHyperlinkButton("misc.btnprocess.tooltip", SYSConst.icon22link, null); btnProcess.setAlignmentX(Component.RIGHT_ALIGNMENT); btnProcess.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { new DlgProcessAssign(resValue, new Closure() { @Override public void execute(Object o) { if (o == null) { return; } Pair<ArrayList<QProcess>, ArrayList<QProcess>> result = (Pair<ArrayList<QProcess>, ArrayList<QProcess>>) o; ArrayList<QProcess> assigned = result.getFirst(); ArrayList<QProcess> unassigned = result.getSecond(); EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); em.lock(em.merge(resident), LockModeType.OPTIMISTIC); ResValue myValue = em.merge(resValue); em.lock(myValue, LockModeType.OPTIMISTIC_FORCE_INCREMENT); ArrayList<SYSVAL2PROCESS> attached = new ArrayList<SYSVAL2PROCESS>( resValue.getAttachedProcessConnections()); for (SYSVAL2PROCESS linkObject : attached) { if (unassigned.contains(linkObject.getQProcess())) { linkObject.getQProcess().getAttachedNReportConnections().remove(linkObject); linkObject.getResValue().getAttachedProcessConnections().remove(linkObject); em.merge(new PReport( SYSTools.xx(PReportTools.PREPORT_TEXT_REMOVE_ELEMENT) + ": " + myValue.getTitle() + " ID: " + myValue.getID(), PReportTools.PREPORT_TYPE_REMOVE_ELEMENT, linkObject.getQProcess())); em.remove(linkObject); } } attached.clear(); for (QProcess qProcess : assigned) { java.util.List<QProcessElement> listElements = qProcess.getElements(); if (!listElements.contains(myValue)) { QProcess myQProcess = em.merge(qProcess); SYSVAL2PROCESS myLinkObject = em .merge(new SYSVAL2PROCESS(myQProcess, myValue)); em.merge(new PReport( SYSTools.xx(PReportTools.PREPORT_TEXT_ASSIGN_ELEMENT) + ": " + myValue.getTitle() + " ID: " + myValue.getID(), PReportTools.PREPORT_TYPE_ASSIGN_ELEMENT, myQProcess)); qProcess.getAttachedResValueConnections().add(myLinkObject); myValue.getAttachedProcessConnections().add(myLinkObject); } } em.getTransaction().commit(); DateTime dt = new DateTime(myValue.getPit()); final String key = vtype.getID() + ".xtypes." + Integer.toString(dt.getYear()) + ".year"; synchronized (mapType2Values) { mapType2Values.get(key).remove(resValue); mapType2Values.get(key).add(myValue); Collections.sort(mapType2Values.get(key)); } createCP4Year(vtype, dt.getYear()); buildPanel(); //GUITools.flashBackground(contentmap.get(keyMonth), Color.YELLOW, 2); } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (RollbackException ole) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } }); } }); btnProcess.setEnabled(!resValue.isObsolete()); pnlMenu.add(btnProcess); } return pnlMenu; }
From source file:org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.java
/** * Synchronizes local groups and users with a {@link UserRegistry} for a particular zone, optionally handling * deletions.//from w w w . j ava2s . c o m * * @param zone * the zone id. This identifier is used to tag all created groups and users, so that in the future we can * tell those that have been deleted from the registry. * @param userRegistry * the user registry for the zone. * @param forceUpdate * Should the complete set of users and groups be updated / created locally or just those known to have * changed since the last sync? When <code>true</code> then <i>all</i> users and groups are queried from * the user registry and updated locally. When <code>false</code> then each source is only queried for * those users and groups modified since the most recent modification date of all the objects last * queried from that same source. * @param isFullSync * Should a complete set of user and group IDs be queried from the user registries in order to determine * deletions? This parameter is independent of <code>force</code> as a separate query is run to process * updates. * @param splitTxns * Can the modifications to Alfresco be split across multiple transactions for maximum performance? If * <code>true</code>, users and groups are created/updated in batches for increased performance. If * <code>false</code>, all users and groups are processed in the current transaction. This is required if * calling synchronously (e.g. in response to an authentication event in the same transaction). * @param visitedZoneIds * the set of zone ids already processed. These zones have precedence over the current zone when it comes * to group name 'collisions'. If a user or group is queried that already exists locally but is tagged * with one of the zones in this set, then it will be ignored as this zone has lower priority. * @param allZoneIds * the set of all zone ids in the authentication chain. Helps us work out whether the zone information * recorded against a user or group is invalid for the current authentication chain and whether the user * or group needs to be 're-zoned'. */ private void syncWithPlugin(final String zone, UserRegistry userRegistry, boolean forceUpdate, boolean isFullSync, boolean splitTxns, final Set<String> visitedZoneIds, final Set<String> allZoneIds) { // Create a prefixed zone ID for use with the authority service final String zoneId = AuthorityService.ZONE_AUTH_EXT_PREFIX + zone; // Batch Process Names final String reservedBatchProcessNames[] = { SyncProcess.GROUP_ANALYSIS.getTitle(zone), SyncProcess.USER_CREATION.getTitle(zone), SyncProcess.MISSING_AUTHORITY.getTitle(zone), SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone), SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone), SyncProcess.PERSON_ASSOCIATION.getTitle(zone), SyncProcess.AUTHORITY_DELETION.getTitle(zone) }; notifySyncDirectoryStart(zone, reservedBatchProcessNames); // Ensure that the zoneId exists before multiple threads start using it this.transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { authorityService.getOrCreateZone(zoneId); return null; } }, false, splitTxns); // The set of zones we associate with new objects (default plus registry specific) final Set<String> zoneSet = getZones(zoneId); long lastModifiedMillis = forceUpdate ? -1 : getMostRecentUpdateTime(ChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId, splitTxns); Date lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis); if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { if (lastModified == null) { ChainingUserRegistrySynchronizer.logger .info("Retrieving all groups from user registry '" + zone + "'"); } else { ChainingUserRegistrySynchronizer.logger.info( "Retrieving groups changed since " + DateFormat.getDateTimeInstance().format(lastModified) + " from user registry '" + zone + "'"); } } // First, analyze the group structure. Create maps of authorities to their parents for associations to create // and delete. Also deal with 'overlaps' with other zones in the authentication chain. final BatchProcessor<NodeDescription> groupProcessor = new BatchProcessor<NodeDescription>( SyncProcess.GROUP_ANALYSIS.getTitle(zone), this.transactionService.getRetryingTransactionHelper(), userRegistry.getGroups(lastModified), this.workerThreads, 20, this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger, this.loggingInterval); class Analyzer extends BaseBatchProcessWorker<NodeDescription> { private final Map<String, String> groupsToCreate = new TreeMap<String, String>(); private final Map<String, Set<String>> personParentAssocsToCreate = newPersonMap(); private final Map<String, Set<String>> personParentAssocsToDelete = newPersonMap(); private Map<String, Set<String>> groupParentAssocsToCreate = new TreeMap<String, Set<String>>(); private final Map<String, Set<String>> groupParentAssocsToDelete = new TreeMap<String, Set<String>>(); private final Map<String, Set<String>> finalGroupChildAssocs = new TreeMap<String, Set<String>>(); private List<String> personsProcessed = new LinkedList<String>(); private Set<String> allZonePersons = Collections.emptySet(); private Set<String> deletionCandidates; private long latestTime; public Analyzer(final long latestTime) { this.latestTime = latestTime; } public long getLatestTime() { return this.latestTime; } public Set<String> getDeletionCandidates() { return this.deletionCandidates; } public String getIdentifier(NodeDescription entry) { return entry.getSourceId(); } public void process(NodeDescription group) throws Throwable { PropertyMap groupProperties = group.getProperties(); String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME); String groupShortName = ChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName); Set<String> groupZones = ChainingUserRegistrySynchronizer.this.authorityService .getAuthorityZones(groupName); if (groupZones == null) { // The group did not exist at all updateGroup(group, false); } else { // Check whether the group is in any of the authentication chain zones Set<String> intersection = new TreeSet<String>(groupZones); intersection.retainAll(allZoneIds); // Check whether the group is in any of the higher priority authentication chain zones Set<String> visited = new TreeSet<String>(intersection); visited.retainAll(visitedZoneIds); if (groupZones.contains(zoneId)) { // The group already existed in this zone: update the group updateGroup(group, true); } else if (!visited.isEmpty()) { // A group that exists in a different zone with higher precedence return; } else if (!allowDeletions || intersection.isEmpty()) { // Deletions are disallowed or the group exists, but not in a zone that's in the authentication // chain. May be due to upgrade or zone changes. Let's re-zone them if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { ChainingUserRegistrySynchronizer.logger.warn("Updating group '" + groupShortName + "'. This group will in future be assumed to originate from user registry '" + zone + "'."); } updateAuthorityZones(groupName, groupZones, zoneSet); // The group now exists in this zone: update the group updateGroup(group, true); } else { // The group existed, but in a zone with lower precedence if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { ChainingUserRegistrySynchronizer.logger.warn("Recreating occluded group '" + groupShortName + "'. This group was previously created through synchronization with a lower priority user registry."); } ChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(groupName); // create the group updateGroup(group, false); } } synchronized (this) { // Maintain the last modified date Date groupLastModified = group.getLastModified(); if (groupLastModified != null) { this.latestTime = Math.max(this.latestTime, groupLastModified.getTime()); } } } // Recursively walks and caches the authorities relating to and from this group so that we can later detect potential cycles private Set<String> getContainedAuthorities(String groupName) { // Return the cached children if it is processed Set<String> children = this.finalGroupChildAssocs.get(groupName); if (children != null) { return children; } // First, recurse to the parent most authorities for (String parent : ChainingUserRegistrySynchronizer.this.authorityService .getContainingAuthorities(null, groupName, true)) { getContainedAuthorities(parent); } // Now descend on unprocessed parents. return cacheContainedAuthorities(groupName); } private Set<String> cacheContainedAuthorities(String groupName) { // Return the cached children if it is processed Set<String> children = this.finalGroupChildAssocs.get(groupName); if (children != null) { return children; } // Descend on unprocessed parents. children = ChainingUserRegistrySynchronizer.this.authorityService.getContainedAuthorities(null, groupName, true); this.finalGroupChildAssocs.put(groupName, children); for (String child : children) { if (AuthorityType.getAuthorityType(child) != AuthorityType.USER) { cacheContainedAuthorities(child); } } return children; } private synchronized void updateGroup(NodeDescription group, boolean existed) { PropertyMap groupProperties = group.getProperties(); String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME); String groupDisplayName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_DISPLAY_NAME); if (groupDisplayName == null) { groupDisplayName = ChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName); } // Divide the child associations into person and group associations, dealing with case sensitivity Set<String> newChildPersons = newPersonSet(); Set<String> newChildGroups = new TreeSet<String>(); for (String child : group.getChildAssociations()) { if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { newChildPersons.add(child); } else { newChildGroups.add(child); } } // Account for differences if already existing if (existed) { // Update the display name now ChainingUserRegistrySynchronizer.this.authorityService.setAuthorityDisplayName(groupName, groupDisplayName); // Work out the association differences for (String child : new TreeSet<String>(getContainedAuthorities(groupName))) { if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { if (!newChildPersons.remove(child)) { recordParentAssociationDeletion(child, groupName); } } else { if (!newChildGroups.remove(child)) { recordParentAssociationDeletion(child, groupName); } } } } // Mark as created if new else { // Make sure each group to be created features in the association deletion map (as these are handled in the same phase) recordParentAssociationDeletion(groupName, null); this.groupsToCreate.put(groupName, groupDisplayName); } // Create new associations for (String child : newChildPersons) { // Make sure each person with association changes features as a key in the deletion map recordParentAssociationDeletion(child, null); recordParentAssociationCreation(child, groupName); } for (String child : newChildGroups) { // Make sure each group with association changes features as a key in the deletion map recordParentAssociationDeletion(child, null); recordParentAssociationCreation(child, groupName); } } private void recordParentAssociationDeletion(String child, String parent) { Map<String, Set<String>> parentAssocs; if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { parentAssocs = this.personParentAssocsToDelete; } else { // Reflect the change in the map of final group associations (for cycle detection later) parentAssocs = this.groupParentAssocsToDelete; if (parent != null) { Set<String> children = this.finalGroupChildAssocs.get(parent); children.remove(child); } } Set<String> parents = parentAssocs.get(child); if (parents == null) { parents = new TreeSet<String>(); parentAssocs.put(child, parents); } if (parent != null) { parents.add(parent); } } private void recordParentAssociationCreation(String child, String parent) { Map<String, Set<String>> parentAssocs = AuthorityType.getAuthorityType(child) == AuthorityType.USER ? this.personParentAssocsToCreate : this.groupParentAssocsToCreate; Set<String> parents = parentAssocs.get(child); if (parents == null) { parents = new TreeSet<String>(); parentAssocs.put(child, parents); } if (parent != null) { parents.add(parent); } } private void validateGroupParentAssocsToCreate() { Iterator<Map.Entry<String, Set<String>>> i = this.groupParentAssocsToCreate.entrySet().iterator(); while (i.hasNext()) { Map.Entry<String, Set<String>> entry = i.next(); String group = entry.getKey(); Set<String> parents = entry.getValue(); Deque<String> visited = new LinkedList<String>(); Iterator<String> j = parents.iterator(); while (j.hasNext()) { String parent = j.next(); visited.add(parent); if (validateAuthorityChildren(visited, group)) { // The association validated - commit it Set<String> children = finalGroupChildAssocs.get(parent); if (children == null) { children = new TreeSet<String>(); finalGroupChildAssocs.put(parent, children); } children.add(group); } else { // The association did not validate - prune it out if (logger.isWarnEnabled()) { ChainingUserRegistrySynchronizer.logger.warn("Not adding group '" + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(group) + "' to group '" + ChainingUserRegistrySynchronizer.this.authorityService .getShortName(parent) + "' as this creates a cyclic relationship"); } j.remove(); } visited.removeLast(); } if (parents.isEmpty()) { i.remove(); } } // Sort the group associations in parent-first order (root groups first) to minimize reindexing overhead Map<String, Set<String>> sortedGroupAssociations = new LinkedHashMap<String, Set<String>>( this.groupParentAssocsToCreate.size() * 2); Deque<String> visited = new LinkedList<String>(); for (String authority : this.groupParentAssocsToCreate.keySet()) { visitGroupParentAssocs(visited, authority, this.groupParentAssocsToCreate, sortedGroupAssociations); } this.groupParentAssocsToCreate = sortedGroupAssociations; } private boolean validateAuthorityChildren(Deque<String> visited, String authority) { if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) { return true; } if (visited.contains(authority)) { return false; } visited.add(authority); try { Set<String> children = this.finalGroupChildAssocs.get(authority); if (children != null) { for (String child : children) { if (!validateAuthorityChildren(visited, child)) { return false; } } } return true; } finally { visited.removeLast(); } } /** * Visits the given authority by recursively visiting its parents in associationsOld and then adding the * authority to associationsNew. Used to sort associationsOld into 'parent-first' order to minimize * reindexing overhead. * * @param visited * The ancestors that form the path to the authority to visit. Allows detection of cyclic child * associations. * @param authority * the authority to visit * @param associationsOld * the association map to sort * @param associationsNew * the association map to add to in parent-first order */ private boolean visitGroupParentAssocs(Deque<String> visited, String authority, Map<String, Set<String>> associationsOld, Map<String, Set<String>> associationsNew) { if (visited.contains(authority)) { // Prevent cyclic paths (Shouldn't happen as we've already validated) return false; } visited.add(authority); try { if (!associationsNew.containsKey(authority)) { Set<String> oldParents = associationsOld.get(authority); if (oldParents != null) { Set<String> newParents = new TreeSet<String>(); for (String parent : oldParents) { if (visitGroupParentAssocs(visited, parent, associationsOld, associationsNew)) { newParents.add(parent); } } associationsNew.put(authority, newParents); } } return true; } finally { visited.removeLast(); } } private Set<String> newPersonSet() { return ChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive() ? new TreeSet<String>() : new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); } private Map<String, Set<String>> newPersonMap() { return ChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive() ? new TreeMap<String, Set<String>>() : new TreeMap<String, Set<String>>(String.CASE_INSENSITIVE_ORDER); } private void logRetainParentAssociations(Map<String, Set<String>> parentAssocs, Set<String> toRetain) { Iterator<Map.Entry<String, Set<String>>> i = parentAssocs.entrySet().iterator(); StringBuilder groupList = null; while (i.hasNext()) { Map.Entry<String, Set<String>> entry = i.next(); String child = entry.getKey(); if (!toRetain.contains(child)) { if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { if (groupList == null) { groupList = new StringBuilder(1024); } else { groupList.setLength(0); } for (String parent : entry.getValue()) { if (groupList.length() > 0) { groupList.append(", "); } groupList.append('\'').append( ChainingUserRegistrySynchronizer.this.authorityService.getShortName(parent)) .append('\''); } ChainingUserRegistrySynchronizer.logger.debug("Ignoring non-existent member '" + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(child) + "' in groups {" + groupList.toString() + "}"); } i.remove(); } } } private void processGroups(UserRegistry userRegistry, boolean isFullSync, boolean splitTxns) { // MNT-12454 fix. If syncDelete is false, there is no need to pull all users and all groups from LDAP during the full synchronization. if ((syncDelete || !groupsToCreate.isEmpty()) && (isFullSync || !this.groupParentAssocsToDelete.isEmpty())) { final Set<String> allZonePersons = newPersonSet(); final Set<String> allZoneGroups = new TreeSet<String>(); // Add in current set of known authorities ChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { public Void execute() throws Throwable { allZonePersons.addAll(ChainingUserRegistrySynchronizer.this.authorityService .getAllAuthoritiesInZone(zoneId, AuthorityType.USER)); allZoneGroups.addAll(ChainingUserRegistrySynchronizer.this.authorityService .getAllAuthoritiesInZone(zoneId, AuthorityType.GROUP)); return null; } }, true, splitTxns); allZoneGroups.addAll(this.groupsToCreate.keySet()); // Prune our set of authorities according to deletions if (isFullSync) { final Set<String> personDeletionCandidates = newPersonSet(); personDeletionCandidates.addAll(allZonePersons); final Set<String> groupDeletionCandidates = new TreeSet<String>(); groupDeletionCandidates.addAll(allZoneGroups); this.deletionCandidates = new TreeSet<String>(); for (String person : userRegistry.getPersonNames()) { personDeletionCandidates.remove(person); } for (String group : userRegistry.getGroupNames()) { groupDeletionCandidates.remove(group); } this.deletionCandidates = new TreeSet<String>(); this.deletionCandidates.addAll(personDeletionCandidates); this.deletionCandidates.addAll(groupDeletionCandidates); if (allowDeletions) { allZonePersons.removeAll(personDeletionCandidates); allZoneGroups.removeAll(groupDeletionCandidates); } else { // Complete association deletion information by scanning deleted groups BatchProcessor<String> groupScanner = new BatchProcessor<String>( zone + " Missing Authority Scanning", ChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.deletionCandidates, ChainingUserRegistrySynchronizer.this.workerThreads, 20, ChainingUserRegistrySynchronizer.this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger, ChainingUserRegistrySynchronizer.this.loggingInterval); groupScanner.process(new BaseBatchProcessWorker<String>() { @Override public String getIdentifier(String entry) { return entry; } @Override public void process(String authority) throws Throwable { //MNT-12454 fix. Modifies an authority's zone. Move authority from AUTH.EXT.LDAP1 to AUTH.ALF. updateAuthorityZones(authority, Collections.singleton(zoneId), Collections.singleton(AuthorityService.ZONE_AUTH_ALFRESCO)); } }, splitTxns); } } // Prune the group associations now that we have complete information this.groupParentAssocsToCreate.keySet().retainAll(allZoneGroups); logRetainParentAssociations(this.groupParentAssocsToCreate, allZoneGroups); this.finalGroupChildAssocs.keySet().retainAll(allZoneGroups); // Pruning person associations will have to wait until we have passed over all persons and built up // this set this.allZonePersons = allZonePersons; if (!this.groupParentAssocsToDelete.isEmpty()) { // Create/update the groups and delete parent associations to be deleted // Batch 4 Group Creation and Association Deletion BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone), ChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.groupParentAssocsToDelete.entrySet(), ChainingUserRegistrySynchronizer.this.workerThreads, 20, ChainingUserRegistrySynchronizer.this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger, ChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(Map.Entry<String, Set<String>> entry) throws Throwable { String child = entry.getKey(); String groupDisplayName = Analyzer.this.groupsToCreate.get(child); if (groupDisplayName != null) { String groupShortName = ChainingUserRegistrySynchronizer.this.authorityService .getShortName(child); if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { ChainingUserRegistrySynchronizer.logger .debug("Creating group '" + groupShortName + "'"); } // create the group ChainingUserRegistrySynchronizer.this.authorityService.createAuthority( AuthorityType.getAuthorityType(child), groupShortName, groupDisplayName, zoneSet); } else { // Maintain association deletions now. The creations will have to be done later once // we have performed all the deletions in order to avoid creating cycles maintainAssociationDeletions(child); } } }, splitTxns); } } } private void finalizeAssociations(UserRegistry userRegistry, boolean splitTxns) { // First validate the group associations to be created for potential cycles. Remove any offending association validateGroupParentAssocsToCreate(); // Now go ahead and create the group associations if (!this.groupParentAssocsToCreate.isEmpty()) { // Batch 5 Group Association Creation BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone), ChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper(), this.groupParentAssocsToCreate.entrySet(), ChainingUserRegistrySynchronizer.this.workerThreads, 20, ChainingUserRegistrySynchronizer.this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger, ChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(Map.Entry<String, Set<String>> entry) throws Throwable { maintainAssociationCreations(entry.getKey()); } }, splitTxns); } // Remove all the associations we have already dealt with this.personParentAssocsToDelete.keySet().removeAll(this.personsProcessed); // Filter out associations to authorities that simply can't exist (and log if debugging is enabled) logRetainParentAssociations(this.personParentAssocsToCreate, this.allZonePersons); // Update associations to persons not updated themselves if (!this.personParentAssocsToDelete.isEmpty()) { // Batch 6 Person Association BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( SyncProcess.PERSON_ASSOCIATION.getTitle(zone), ChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper(), this.personParentAssocsToDelete.entrySet(), ChainingUserRegistrySynchronizer.this.workerThreads, 20, ChainingUserRegistrySynchronizer.this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger, ChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(Map.Entry<String, Set<String>> entry) throws Throwable { maintainAssociationDeletions(entry.getKey()); maintainAssociationCreations(entry.getKey()); } }, splitTxns); } } private void maintainAssociationDeletions(String authorityName) { boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER; Set<String> parentsToDelete = isPerson ? this.personParentAssocsToDelete.get(authorityName) : this.groupParentAssocsToDelete.get(authorityName); if (parentsToDelete != null && !parentsToDelete.isEmpty()) { for (String parent : parentsToDelete) { if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { ChainingUserRegistrySynchronizer.logger.debug("Removing '" + ChainingUserRegistrySynchronizer.this.authorityService .getShortName(authorityName) + "' from group '" + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(parent) + "'"); } ChainingUserRegistrySynchronizer.this.authorityService.removeAuthority(parent, authorityName); } } } private void maintainAssociationCreations(String authorityName) { boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER; Set<String> parents = isPerson ? this.personParentAssocsToCreate.get(authorityName) : this.groupParentAssocsToCreate.get(authorityName); if (parents != null && !parents.isEmpty()) { if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { for (String groupName : parents) { ChainingUserRegistrySynchronizer.logger.debug("Adding '" + ChainingUserRegistrySynchronizer.this.authorityService .getShortName(authorityName) + "' to group '" + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(groupName) + "'"); } } try { ChainingUserRegistrySynchronizer.this.authorityService.addAuthority(parents, authorityName); } catch (UnknownAuthorityException e) { // Let's force a transaction retry if a parent doesn't exist. It may be because we are // waiting for another worker thread to create it throw new ConcurrencyFailureException("Forcing batch retry for unknown authority", e); } catch (InvalidNodeRefException e) { // Another thread may have written the node, but it is not visible to this transaction // See: ALF-5471: 'authorityMigration' patch can report 'Node does not exist' throw new ConcurrencyFailureException("Forcing batch retry for invalid node", e); } } // Remember that this person's associations have been maintained if (isPerson) { synchronized (this) { this.personsProcessed.add(authorityName); } } } } // end of Analyzer class // Run the first process the Group Analyzer final Analyzer groupAnalyzer = new Analyzer(lastModifiedMillis); int groupProcessedCount = groupProcessor.process(groupAnalyzer, splitTxns); groupAnalyzer.processGroups(userRegistry, isFullSync, splitTxns); // Process persons and their parent associations lastModifiedMillis = forceUpdate ? -1 : getMostRecentUpdateTime(ChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId, splitTxns); lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis); if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { if (lastModified == null) { ChainingUserRegistrySynchronizer.logger .info("Retrieving all users from user registry '" + zone + "'"); } else { ChainingUserRegistrySynchronizer.logger.info( "Retrieving users changed since " + DateFormat.getDateTimeInstance().format(lastModified) + " from user registry '" + zone + "'"); } } // User Creation and Association final BatchProcessor<NodeDescription> personProcessor = new BatchProcessor<NodeDescription>( SyncProcess.USER_CREATION.getTitle(zone), this.transactionService.getRetryingTransactionHelper(), userRegistry.getPersons(lastModified), this.workerThreads, 10, this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger, this.loggingInterval); final UserRegistry userRegistryFinalRef = userRegistry; class PersonWorker extends BaseBatchProcessWorker<NodeDescription> { private long latestTime; public PersonWorker(final long latestTime) { this.latestTime = latestTime; } public long getLatestTime() { return this.latestTime; } public String getIdentifier(NodeDescription entry) { return entry.getSourceId(); } public void process(NodeDescription person) throws Throwable { // Make a mutable copy of the person properties, since they get written back to by person service HashMap<QName, Serializable> personProperties = new HashMap<QName, Serializable>( person.getProperties()); String personName = personProperties.get(ContentModel.PROP_USERNAME).toString().trim(); personProperties.put(ContentModel.PROP_USERNAME, personName); if (Boolean.parseBoolean(ChainingUserRegistrySynchronizer.this.externalUserControl) && ChainingUserRegistrySynchronizer.this.externalUserControlSubsystemName.equals(zone) && userRegistryFinalRef instanceof LDAPUserRegistry) { try { LDAPUserRegistry ldapUserRegistry = (LDAPUserRegistry) userRegistryFinalRef; if (ldapUserRegistry.getUserAccountStatusInterpreter() != null) { QName propertyNameToCheck = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userAccountStatusProperty"); if (personProperties.get(propertyNameToCheck) != null || ldapUserRegistry.getUserAccountStatusInterpreter().acceptsNullArgument()) { boolean isUserAccountDisabled = ldapUserRegistry.getUserAccountStatusInterpreter() .isUserAccountDisabled(personProperties.get(propertyNameToCheck)); personProperties.put(ContentModel.PROP_ENABLED, !isUserAccountDisabled); } } } catch (IllegalArgumentException iae) { // Can be thrown by certain implementations of AbstractDirectoryServiceUserAccountStatusInterpreter; // We'll just log it. ChainingUserRegistrySynchronizer.logger.debug(iae.getMessage(), iae); } } // for invalid names will throw ConstraintException that will be catched by BatchProcessor$TxnCallback nameChecker.evaluate(personName); Set<String> zones = ChainingUserRegistrySynchronizer.this.authorityService .getAuthorityZones(personName); if (zones == null) { // The person did not exist at all if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { ChainingUserRegistrySynchronizer.logger.debug("Creating user '" + personName + "'"); } ChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet); } else if (zones.contains(zoneId)) { // The person already existed in this zone: update the person if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { ChainingUserRegistrySynchronizer.logger.debug("Updating user '" + personName + "'"); } ChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName, personProperties, false); } else { // Check whether the user is in any of the authentication chain zones Set<String> intersection = new TreeSet<String>(zones); intersection.retainAll(allZoneIds); // Check whether the user is in any of the higher priority authentication chain zones Set<String> visited = new TreeSet<String>(intersection); visited.retainAll(visitedZoneIds); if (visited.size() > 0) { // A person that exists in a different zone with higher precedence - ignore return; } else if (!allowDeletions || intersection.isEmpty()) { // The person exists, but in a different zone. Either deletions are disallowed or the zone is // not in the authentication chain. May be due to upgrade or zone changes. Let's re-zone them if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { ChainingUserRegistrySynchronizer.logger.warn("Updating user '" + personName + "'. This user will in future be assumed to originate from user registry '" + zone + "'."); } updateAuthorityZones(personName, zones, zoneSet); ChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName, personProperties, false); } else { // The person existed, but in a zone with lower precedence if (ChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { ChainingUserRegistrySynchronizer.logger.warn("Recreating occluded user '" + personName + "'. This user was previously created through synchronization with a lower priority user registry."); } ChainingUserRegistrySynchronizer.this.personService.deletePerson(personName); ChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet); } } // Maintain association deletions and creations in one shot (safe to do this with persons as we can't // create cycles) groupAnalyzer.maintainAssociationDeletions(personName); groupAnalyzer.maintainAssociationCreations(personName); synchronized (this) { // Maintain the last modified date Date personLastModified = person.getLastModified(); if (personLastModified != null) { this.latestTime = Math.max(this.latestTime, personLastModified.getTime()); } } } } PersonWorker persons = new PersonWorker(lastModifiedMillis); int personProcessedCount = personProcessor.process(persons, splitTxns); // Process those associations to persons who themselves have not been updated groupAnalyzer.finalizeAssociations(userRegistry, splitTxns); // Only now that the whole tree has been processed is it safe to persist the last modified dates long latestTime = groupAnalyzer.getLatestTime(); if (latestTime != -1) { setMostRecentUpdateTime(ChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId, latestTime, splitTxns); } latestTime = persons.getLatestTime(); if (latestTime != -1) { setMostRecentUpdateTime(ChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId, latestTime, splitTxns); } // Delete authorities if we have complete information for the zone Set<String> deletionCandidates = groupAnalyzer.getDeletionCandidates(); if (isFullSync && allowDeletions && !deletionCandidates.isEmpty()) { // Batch 7 Authority Deletion BatchProcessor<String> authorityDeletionProcessor = new BatchProcessor<String>( SyncProcess.AUTHORITY_DELETION.getTitle(zone), this.transactionService.getRetryingTransactionHelper(), deletionCandidates, this.workerThreads, 10, this.applicationEventPublisher, ChainingUserRegistrySynchronizer.logger, this.loggingInterval); class AuthorityDeleter extends BaseBatchProcessWorker<String> { private int personProcessedCount; private int groupProcessedCount; public int getPersonProcessedCount() { return this.personProcessedCount; } public int getGroupProcessedCount() { return this.groupProcessedCount; } public String getIdentifier(String entry) { return entry; } public void process(String authority) throws Throwable { if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) { if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { ChainingUserRegistrySynchronizer.logger.debug("Deleting user '" + authority + "'"); } ChainingUserRegistrySynchronizer.this.personService.deletePerson(authority); synchronized (this) { this.personProcessedCount++; } } else { if (ChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { ChainingUserRegistrySynchronizer.logger.debug("Deleting group '" + ChainingUserRegistrySynchronizer.this.authorityService.getShortName(authority) + "'"); } ChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(authority); synchronized (this) { this.groupProcessedCount++; } } } } AuthorityDeleter authorityDeleter = new AuthorityDeleter(); authorityDeletionProcessor.process(authorityDeleter, splitTxns); groupProcessedCount += authorityDeleter.getGroupProcessedCount(); personProcessedCount += authorityDeleter.getPersonProcessedCount(); } // Remember we have visited this zone visitedZoneIds.add(zoneId); Object statusParams[] = { personProcessedCount, groupProcessedCount }; final String statusMessage = I18NUtil.getMessage("synchronization.summary.status", statusParams); if (ChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { ChainingUserRegistrySynchronizer.logger .info("Finished synchronizing users and groups with user registry '" + zone + "'"); ChainingUserRegistrySynchronizer.logger.info(statusMessage); } notifySyncDirectoryEnd(zone, statusMessage); }
From source file:org.cggh.repo.security.sync.CustomChainingUserRegistrySynchronizer.java
/** * Synchronizes local groups and users with a {@link UserRegistry} for a particular zone, optionally handling * deletions.//from www . ja v a 2 s .co m * * @param zone * the zone id. This identifier is used to tag all created groups and users, so that in the future we can * tell those that have been deleted from the registry. * @param userRegistry * the user registry for the zone. * @param forceUpdate * Should the complete set of users and groups be updated / created locally or just those known to have * changed since the last sync? When <code>true</code> then <i>all</i> users and groups are queried from * the user registry and updated locally. When <code>false</code> then each source is only queried for * those users and groups modified since the most recent modification date of all the objects last * queried from that same source. * @param isFullSync * Should a complete set of user and group IDs be queried from the user registries in order to determine * deletions? This parameter is independent of <code>force</code> as a separate query is run to process * updates. * @param splitTxns * Can the modifications to Alfresco be split across multiple transactions for maximum performance? If * <code>true</code>, users and groups are created/updated in batches for increased performance. If * <code>false</code>, all users and groups are processed in the current transaction. This is required if * calling synchronously (e.g. in response to an authentication event in the same transaction). * @param visitedZoneIds * the set of zone ids already processed. These zones have precedence over the current zone when it comes * to group name 'collisions'. If a user or group is queried that already exists locally but is tagged * with one of the zones in this set, then it will be ignored as this zone has lower priority. * @param allZoneIds * the set of all zone ids in the authentication chain. Helps us work out whether the zone information * recorded against a user or group is invalid for the current authentication chain and whether the user * or group needs to be 're-zoned'. */ private void syncWithPlugin(final String zone, UserRegistry userRegistry, boolean forceUpdate, boolean isFullSync, boolean splitTxns, final Set<String> visitedZoneIds, final Set<String> allZoneIds) { // Create a prefixed zone ID for use with the authority service final String zoneId = AuthorityService.ZONE_AUTH_EXT_PREFIX + zone; // Batch Process Names final String reservedBatchProcessNames[] = { SyncProcess.GROUP_ANALYSIS.getTitle(zone), SyncProcess.USER_CREATION.getTitle(zone), SyncProcess.MISSING_AUTHORITY.getTitle(zone), SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone), SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone), SyncProcess.PERSON_ASSOCIATION.getTitle(zone), SyncProcess.AUTHORITY_DELETION.getTitle(zone) }; notifySyncDirectoryStart(zone, reservedBatchProcessNames); // Ensure that the zoneId exists before multiple threads start using it this.transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { authorityService.getOrCreateZone(zoneId); return null; } }, false, splitTxns); // The set of zones we associate with new objects (default plus registry specific) final Set<String> zoneSet = getZones(zoneId); long lastModifiedMillis = forceUpdate ? -1 : getMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId, splitTxns); Date lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis); if (CustomChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { if (lastModified == null) { CustomChainingUserRegistrySynchronizer.logger .info("Retrieving all groups from user registry '" + zone + "'"); } else { CustomChainingUserRegistrySynchronizer.logger.info( "Retrieving groups changed since " + DateFormat.getDateTimeInstance().format(lastModified) + " from user registry '" + zone + "'"); } } // First, analyze the group structure. Create maps of authorities to their parents for associations to create // and delete. Also deal with 'overlaps' with other zones in the authentication chain. final BatchProcessor<NodeDescription> groupProcessor = new BatchProcessor<NodeDescription>( SyncProcess.GROUP_ANALYSIS.getTitle(zone), this.transactionService.getRetryingTransactionHelper(), userRegistry.getGroups(lastModified), this.workerThreads, 20, this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger, this.loggingInterval); class Analyzer extends BaseBatchProcessWorker<NodeDescription> { private final Map<String, String> groupsToCreate = new TreeMap<String, String>(); private final Map<String, Set<String>> personParentAssocsToCreate = newPersonMap(); private final Map<String, Set<String>> personParentAssocsToDelete = newPersonMap(); private Map<String, Set<String>> groupParentAssocsToCreate = new TreeMap<String, Set<String>>(); private final Map<String, Set<String>> groupParentAssocsToDelete = new TreeMap<String, Set<String>>(); private final Map<String, Set<String>> finalGroupChildAssocs = new TreeMap<String, Set<String>>(); private List<String> personsProcessed = new LinkedList<String>(); private Set<String> allZonePersons = Collections.emptySet(); private Set<String> deletionCandidates; private long latestTime; public Analyzer(final long latestTime) { this.latestTime = latestTime; } public long getLatestTime() { return this.latestTime; } public Set<String> getDeletionCandidates() { return this.deletionCandidates; } public String getIdentifier(NodeDescription entry) { return entry.getSourceId(); } public void process(NodeDescription group) throws Throwable { PropertyMap groupProperties = group.getProperties(); String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME); String groupShortName = CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName); Set<String> groupZones = CustomChainingUserRegistrySynchronizer.this.authorityService .getAuthorityZones(groupName); if (groupZones == null) { // The group did not exist at all updateGroup(group, false); } else { // Check whether the group is in any of the authentication chain zones Set<String> intersection = new TreeSet<String>(groupZones); intersection.retainAll(allZoneIds); // Check whether the group is in any of the higher priority authentication chain zones Set<String> visited = new TreeSet<String>(intersection); visited.retainAll(visitedZoneIds); if (groupZones.contains(zoneId)) { // The group already existed in this zone: update the group updateGroup(group, true); } else if (!visited.isEmpty()) { // A group that exists in a different zone with higher precedence return; } else if (!allowDeletions || intersection.isEmpty()) { // Deletions are disallowed or the group exists, but not in a zone that's in the authentication // chain. May be due to upgrade or zone changes. Let's re-zone them if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { CustomChainingUserRegistrySynchronizer.logger.warn("Updating group '" + groupShortName + "'. This group will in future be assumed to originate from user registry '" + zone + "'."); } updateAuthorityZones(groupName, groupZones, zoneSet); // The group now exists in this zone: update the group updateGroup(group, true); } else { // The group existed, but in a zone with lower precedence if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { CustomChainingUserRegistrySynchronizer.logger.warn("Recreating occluded group '" + groupShortName + "'. This group was previously created through synchronization with a lower priority user registry."); } CustomChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(groupName); // create the group updateGroup(group, false); } } synchronized (this) { // Maintain the last modified date Date groupLastModified = group.getLastModified(); if (groupLastModified != null) { this.latestTime = Math.max(this.latestTime, groupLastModified.getTime()); } } } // Recursively walks and caches the authorities relating to and from this group so that we can later detect potential cycles private Set<String> getContainedAuthorities(String groupName) { // Return the cached children if it is processed Set<String> children = this.finalGroupChildAssocs.get(groupName); if (children != null) { return children; } // First, recurse to the parent most authorities for (String parent : CustomChainingUserRegistrySynchronizer.this.authorityService .getContainingAuthorities(null, groupName, true)) { getContainedAuthorities(parent); } // Now descend on unprocessed parents. return cacheContainedAuthorities(groupName); } private Set<String> cacheContainedAuthorities(String groupName) { // Return the cached children if it is processed Set<String> children = this.finalGroupChildAssocs.get(groupName); if (children != null) { return children; } // Descend on unprocessed parents. children = CustomChainingUserRegistrySynchronizer.this.authorityService .getContainedAuthorities(null, groupName, true); this.finalGroupChildAssocs.put(groupName, children); for (String child : children) { if (AuthorityType.getAuthorityType(child) != AuthorityType.USER) { cacheContainedAuthorities(child); } } return children; } private synchronized void updateGroup(NodeDescription group, boolean existed) { PropertyMap groupProperties = group.getProperties(); String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME); String groupDisplayName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_DISPLAY_NAME); if (groupDisplayName == null) { groupDisplayName = CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName); } // Divide the child associations into person and group associations, dealing with case sensitivity Set<String> newChildPersons = newPersonSet(); Set<String> newChildGroups = new TreeSet<String>(); for (String child : group.getChildAssociations()) { if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { newChildPersons.add(child); } else { newChildGroups.add(child); } } // Account for differences if already existing if (existed) { // Update the display name now CustomChainingUserRegistrySynchronizer.this.authorityService.setAuthorityDisplayName(groupName, groupDisplayName); // Work out the association differences for (String child : new TreeSet<String>(getContainedAuthorities(groupName))) { if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { if (!newChildPersons.remove(child)) { recordParentAssociationDeletion(child, groupName); } } else { if (!newChildGroups.remove(child)) { recordParentAssociationDeletion(child, groupName); } } } } // Mark as created if new else { // Make sure each group to be created features in the association deletion map (as these are handled in the same phase) recordParentAssociationDeletion(groupName, null); this.groupsToCreate.put(groupName, groupDisplayName); } // Create new associations for (String child : newChildPersons) { // Make sure each person with association changes features as a key in the deletion map recordParentAssociationDeletion(child, null); recordParentAssociationCreation(child, groupName); } for (String child : newChildGroups) { // Make sure each group with association changes features as a key in the deletion map recordParentAssociationDeletion(child, null); recordParentAssociationCreation(child, groupName); } } private void recordParentAssociationDeletion(String child, String parent) { Map<String, Set<String>> parentAssocs; if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { parentAssocs = this.personParentAssocsToDelete; } else { // Reflect the change in the map of final group associations (for cycle detection later) parentAssocs = this.groupParentAssocsToDelete; if (parent != null) { Set<String> children = this.finalGroupChildAssocs.get(parent); children.remove(child); } } Set<String> parents = parentAssocs.get(child); if (parents == null) { parents = new TreeSet<String>(); parentAssocs.put(child, parents); } if (parent != null) { parents.add(parent); } } private void recordParentAssociationCreation(String child, String parent) { Map<String, Set<String>> parentAssocs = AuthorityType.getAuthorityType(child) == AuthorityType.USER ? this.personParentAssocsToCreate : this.groupParentAssocsToCreate; Set<String> parents = parentAssocs.get(child); if (parents == null) { parents = new TreeSet<String>(); parentAssocs.put(child, parents); } if (parent != null) { parents.add(parent); } } private void validateGroupParentAssocsToCreate() { Iterator<Map.Entry<String, Set<String>>> i = this.groupParentAssocsToCreate.entrySet().iterator(); while (i.hasNext()) { Map.Entry<String, Set<String>> entry = i.next(); String group = entry.getKey(); Set<String> parents = entry.getValue(); Deque<String> visited = new LinkedList<String>(); Iterator<String> j = parents.iterator(); while (j.hasNext()) { String parent = j.next(); visited.add(parent); if (validateAuthorityChildren(visited, group)) { // The association validated - commit it Set<String> children = finalGroupChildAssocs.get(parent); if (children == null) { children = new TreeSet<String>(); finalGroupChildAssocs.put(parent, children); } children.add(group); } else { // The association did not validate - prune it out if (logger.isWarnEnabled()) { CustomChainingUserRegistrySynchronizer.logger.warn("Not adding group '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(group) + "' to group '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(parent) + "' as this creates a cyclic relationship"); } j.remove(); } visited.removeLast(); } if (parents.isEmpty()) { i.remove(); } } // Sort the group associations in parent-first order (root groups first) to minimize reindexing overhead Map<String, Set<String>> sortedGroupAssociations = new LinkedHashMap<String, Set<String>>( this.groupParentAssocsToCreate.size() * 2); Deque<String> visited = new LinkedList<String>(); for (String authority : this.groupParentAssocsToCreate.keySet()) { visitGroupParentAssocs(visited, authority, this.groupParentAssocsToCreate, sortedGroupAssociations); } this.groupParentAssocsToCreate = sortedGroupAssociations; } private boolean validateAuthorityChildren(Deque<String> visited, String authority) { if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) { return true; } if (visited.contains(authority)) { return false; } visited.add(authority); try { Set<String> children = this.finalGroupChildAssocs.get(authority); if (children != null) { for (String child : children) { if (!validateAuthorityChildren(visited, child)) { return false; } } } return true; } finally { visited.removeLast(); } } /** * Visits the given authority by recursively visiting its parents in associationsOld and then adding the * authority to associationsNew. Used to sort associationsOld into 'parent-first' order to minimize * reindexing overhead. * * @param visited * The ancestors that form the path to the authority to visit. Allows detection of cyclic child * associations. * @param authority * the authority to visit * @param associationsOld * the association map to sort * @param associationsNew * the association map to add to in parent-first order */ private boolean visitGroupParentAssocs(Deque<String> visited, String authority, Map<String, Set<String>> associationsOld, Map<String, Set<String>> associationsNew) { if (visited.contains(authority)) { // Prevent cyclic paths (Shouldn't happen as we've already validated) return false; } visited.add(authority); try { if (!associationsNew.containsKey(authority)) { Set<String> oldParents = associationsOld.get(authority); if (oldParents != null) { Set<String> newParents = new TreeSet<String>(); for (String parent : oldParents) { if (visitGroupParentAssocs(visited, parent, associationsOld, associationsNew)) { newParents.add(parent); } } associationsNew.put(authority, newParents); } } return true; } finally { visited.removeLast(); } } private Set<String> newPersonSet() { return CustomChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive() ? new TreeSet<String>() : new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); } private Map<String, Set<String>> newPersonMap() { return CustomChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive() ? new TreeMap<String, Set<String>>() : new TreeMap<String, Set<String>>(String.CASE_INSENSITIVE_ORDER); } private void logRetainParentAssociations(Map<String, Set<String>> parentAssocs, Set<String> toRetain) { Iterator<Map.Entry<String, Set<String>>> i = parentAssocs.entrySet().iterator(); StringBuilder groupList = null; while (i.hasNext()) { Map.Entry<String, Set<String>> entry = i.next(); String child = entry.getKey(); if (!toRetain.contains(child)) { if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { if (groupList == null) { groupList = new StringBuilder(1024); } else { groupList.setLength(0); } for (String parent : entry.getValue()) { if (groupList.length() > 0) { groupList.append(", "); } groupList.append('\'') .append(CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(parent)) .append('\''); } CustomChainingUserRegistrySynchronizer.logger .debug("Ignoring non-existent member '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(child) + "' in groups {" + groupList.toString() + "}"); } i.remove(); } } } private void processGroups(UserRegistry userRegistry, boolean isFullSync, boolean splitTxns) { // MNT-12454 fix. If syncDelete is false, there is no need to pull all users and all groups from LDAP during the full synchronization. if ((syncDelete || !groupsToCreate.isEmpty()) && (isFullSync || !this.groupParentAssocsToDelete.isEmpty())) { final Set<String> allZonePersons = newPersonSet(); final Set<String> allZoneGroups = new TreeSet<String>(); // Add in current set of known authorities CustomChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { public Void execute() throws Throwable { allZonePersons .addAll(CustomChainingUserRegistrySynchronizer.this.authorityService .getAllAuthoritiesInZone(zoneId, AuthorityType.USER)); allZoneGroups .addAll(CustomChainingUserRegistrySynchronizer.this.authorityService .getAllAuthoritiesInZone(zoneId, AuthorityType.GROUP)); return null; } }, true, splitTxns); allZoneGroups.addAll(this.groupsToCreate.keySet()); // Prune our set of authorities according to deletions if (isFullSync) { final Set<String> personDeletionCandidates = newPersonSet(); personDeletionCandidates.addAll(allZonePersons); final Set<String> groupDeletionCandidates = new TreeSet<String>(); groupDeletionCandidates.addAll(allZoneGroups); this.deletionCandidates = new TreeSet<String>(); for (String person : userRegistry.getPersonNames()) { personDeletionCandidates.remove(person); } for (String group : userRegistry.getGroupNames()) { groupDeletionCandidates.remove(group); } this.deletionCandidates = new TreeSet<String>(); this.deletionCandidates.addAll(personDeletionCandidates); this.deletionCandidates.addAll(groupDeletionCandidates); if (allowDeletions) { allZonePersons.removeAll(personDeletionCandidates); allZoneGroups.removeAll(groupDeletionCandidates); } else { // Complete association deletion information by scanning deleted groups BatchProcessor<String> groupScanner = new BatchProcessor<String>( zone + " Missing Authority Scanning", CustomChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.deletionCandidates, CustomChainingUserRegistrySynchronizer.this.workerThreads, 20, CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger, CustomChainingUserRegistrySynchronizer.this.loggingInterval); groupScanner.process(new BaseBatchProcessWorker<String>() { @Override public String getIdentifier(String entry) { return entry; } @Override public void process(String authority) throws Throwable { //MNT-12454 fix. Modifies an authority's zone. Move authority from AUTH.EXT.LDAP1 to AUTH.ALF. updateAuthorityZones(authority, Collections.singleton(zoneId), Collections.singleton(AuthorityService.ZONE_AUTH_ALFRESCO)); } }, splitTxns); } } // Prune the group associations now that we have complete information this.groupParentAssocsToCreate.keySet().retainAll(allZoneGroups); logRetainParentAssociations(this.groupParentAssocsToCreate, allZoneGroups); this.finalGroupChildAssocs.keySet().retainAll(allZoneGroups); // Pruning person associations will have to wait until we have passed over all persons and built up // this set this.allZonePersons = allZonePersons; if (!this.groupParentAssocsToDelete.isEmpty()) { // Create/update the groups and delete parent associations to be deleted // Batch 4 Group Creation and Association Deletion BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( SyncProcess.GROUP_CREATION_AND_ASSOCIATION_DELETION.getTitle(zone), CustomChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.groupParentAssocsToDelete.entrySet(), CustomChainingUserRegistrySynchronizer.this.workerThreads, 20, CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger, CustomChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(Map.Entry<String, Set<String>> entry) throws Throwable { String child = entry.getKey(); String groupDisplayName = Analyzer.this.groupsToCreate.get(child); if (groupDisplayName != null) { String groupShortName = CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(child); if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { CustomChainingUserRegistrySynchronizer.logger .debug("Creating group '" + groupShortName + "'"); } // create the group CustomChainingUserRegistrySynchronizer.this.authorityService.createAuthority( AuthorityType.getAuthorityType(child), groupShortName, groupDisplayName, zoneSet); } else { // Maintain association deletions now. The creations will have to be done later once // we have performed all the deletions in order to avoid creating cycles maintainAssociationDeletions(child); } } }, splitTxns); } } } private void finalizeAssociations(UserRegistry userRegistry, boolean splitTxns) { // First validate the group associations to be created for potential cycles. Remove any offending association validateGroupParentAssocsToCreate(); // Now go ahead and create the group associations if (!this.groupParentAssocsToCreate.isEmpty()) { // Batch 5 Group Association Creation BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( SyncProcess.GROUP_ASSOCIATION_CREATION.getTitle(zone), CustomChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.groupParentAssocsToCreate.entrySet(), CustomChainingUserRegistrySynchronizer.this.workerThreads, 20, CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger, CustomChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(Map.Entry<String, Set<String>> entry) throws Throwable { maintainAssociationCreations(entry.getKey()); } }, splitTxns); } // Remove all the associations we have already dealt with this.personParentAssocsToDelete.keySet().removeAll(this.personsProcessed); // Filter out associations to authorities that simply can't exist (and log if debugging is enabled) logRetainParentAssociations(this.personParentAssocsToCreate, this.allZonePersons); // Update associations to persons not updated themselves if (!this.personParentAssocsToDelete.isEmpty()) { // Batch 6 Person Association BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( SyncProcess.PERSON_ASSOCIATION.getTitle(zone), CustomChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.personParentAssocsToDelete.entrySet(), CustomChainingUserRegistrySynchronizer.this.workerThreads, 20, CustomChainingUserRegistrySynchronizer.this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger, CustomChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(Map.Entry<String, Set<String>> entry) throws Throwable { maintainAssociationDeletions(entry.getKey()); maintainAssociationCreations(entry.getKey()); } }, splitTxns); } } private void maintainAssociationDeletions(String authorityName) { boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER; Set<String> parentsToDelete = isPerson ? this.personParentAssocsToDelete.get(authorityName) : this.groupParentAssocsToDelete.get(authorityName); if (parentsToDelete != null && !parentsToDelete.isEmpty()) { for (String parent : parentsToDelete) { if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { CustomChainingUserRegistrySynchronizer.logger.debug("Removing '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(authorityName) + "' from group '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(parent) + "'"); } CustomChainingUserRegistrySynchronizer.this.authorityService.removeAuthority(parent, authorityName); } } } private void maintainAssociationCreations(String authorityName) { boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER; Set<String> parents = isPerson ? this.personParentAssocsToCreate.get(authorityName) : this.groupParentAssocsToCreate.get(authorityName); if (parents != null && !parents.isEmpty()) { if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { for (String groupName : parents) { CustomChainingUserRegistrySynchronizer.logger.debug("Adding '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(authorityName) + "' to group '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName) + "'"); } } try { CustomChainingUserRegistrySynchronizer.this.authorityService.addAuthority(parents, authorityName); } catch (UnknownAuthorityException e) { // Let's force a transaction retry if a parent doesn't exist. It may be because we are // waiting for another worker thread to create it throw new ConcurrencyFailureException("Forcing batch retry for unknown authority", e); } catch (InvalidNodeRefException e) { // Another thread may have written the node, but it is not visible to this transaction // See: ALF-5471: 'authorityMigration' patch can report 'Node does not exist' throw new ConcurrencyFailureException("Forcing batch retry for invalid node", e); } } // Remember that this person's associations have been maintained if (isPerson) { synchronized (this) { this.personsProcessed.add(authorityName); } } } } // end of Analyzer class // Run the first process the Group Analyzer final Analyzer groupAnalyzer = new Analyzer(lastModifiedMillis); int groupProcessedCount = groupProcessor.process(groupAnalyzer, splitTxns); groupAnalyzer.processGroups(userRegistry, isFullSync, splitTxns); // Process persons and their parent associations lastModifiedMillis = forceUpdate ? -1 : getMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId, splitTxns); lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis); if (CustomChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { if (lastModified == null) { CustomChainingUserRegistrySynchronizer.logger .info("Retrieving all users from user registry '" + zone + "'"); } else { CustomChainingUserRegistrySynchronizer.logger.info( "Retrieving users changed since " + DateFormat.getDateTimeInstance().format(lastModified) + " from user registry '" + zone + "'"); } } // User Creation and Association final BatchProcessor<NodeDescription> personProcessor = new BatchProcessor<NodeDescription>( SyncProcess.USER_CREATION.getTitle(zone), this.transactionService.getRetryingTransactionHelper(), userRegistry.getPersons(lastModified), this.workerThreads, 10, this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger, this.loggingInterval); class PersonWorker extends BaseBatchProcessWorker<NodeDescription> { private long latestTime; public PersonWorker(final long latestTime) { this.latestTime = latestTime; } public long getLatestTime() { return this.latestTime; } public String getIdentifier(NodeDescription entry) { return entry.getSourceId(); } public void process(NodeDescription person) throws Throwable { // Make a mutable copy of the person properties, since they get written back to by person service HashMap<QName, Serializable> personProperties = new HashMap<QName, Serializable>( person.getProperties()); String personName = personProperties.get(ContentModel.PROP_USERNAME).toString().trim(); personProperties.put(ContentModel.PROP_USERNAME, personName); // for invalid names will throw ConstraintException that will be catched by BatchProcessor$TxnCallback nameChecker.evaluate(personName); Set<String> zones = CustomChainingUserRegistrySynchronizer.this.authorityService .getAuthorityZones(personName); if (zones == null) { // The person did not exist at all if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { CustomChainingUserRegistrySynchronizer.logger.debug("Creating user '" + personName + "'"); } CustomChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet); CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName, person.getProperties(), getLatestTime()); } else if (zones.contains(zoneId)) { // The person already existed in this zone: update the person if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { CustomChainingUserRegistrySynchronizer.logger.debug("Updating user '" + personName + "'"); } CustomChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName, personProperties, false); CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName, person.getProperties(), getLatestTime()); } else { // Check whether the user is in any of the authentication chain zones Set<String> intersection = new TreeSet<String>(zones); intersection.retainAll(allZoneIds); // Check whether the user is in any of the higher priority authentication chain zones Set<String> visited = new TreeSet<String>(intersection); visited.retainAll(visitedZoneIds); if (visited.size() > 0) { // A person that exists in a different zone with higher precedence - ignore return; } else if (!allowDeletions || intersection.isEmpty()) { // The person exists, but in a different zone. Either deletions are disallowed or the zone is // not in the authentication chain. May be due to upgrade or zone changes. Let's re-zone them if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { CustomChainingUserRegistrySynchronizer.logger.warn("Updating user '" + personName + "'. This user will in future be assumed to originate from user registry '" + zone + "'."); } updateAuthorityZones(personName, zones, zoneSet); CustomChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName, personProperties, false); CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName, person.getProperties(), getLatestTime()); } else { // The person existed, but in a zone with lower precedence if (CustomChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { CustomChainingUserRegistrySynchronizer.logger.warn("Recreating occluded user '" + personName + "'. This user was previously created through synchronization with a lower priority user registry."); } CustomChainingUserRegistrySynchronizer.this.personService.deletePerson(personName); CustomChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet); CustomChainingUserRegistrySynchronizer.this.avatarService.setAvatar(personName, person.getProperties(), getLatestTime()); } } // Maintain association deletions and creations in one shot (safe to do this with persons as we can't // create cycles) groupAnalyzer.maintainAssociationDeletions(personName); groupAnalyzer.maintainAssociationCreations(personName); synchronized (this) { // Maintain the last modified date Date personLastModified = person.getLastModified(); if (personLastModified != null) { this.latestTime = Math.max(this.latestTime, personLastModified.getTime()); } } } } PersonWorker persons = new PersonWorker(lastModifiedMillis); int personProcessedCount = personProcessor.process(persons, splitTxns); // Process those associations to persons who themselves have not been updated groupAnalyzer.finalizeAssociations(userRegistry, splitTxns); // Only now that the whole tree has been processed is it safe to persist the last modified dates long latestTime = groupAnalyzer.getLatestTime(); if (latestTime != -1) { setMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId, latestTime, splitTxns); } latestTime = persons.getLatestTime(); if (latestTime != -1) { setMostRecentUpdateTime(CustomChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId, latestTime, splitTxns); } // Delete authorities if we have complete information for the zone Set<String> deletionCandidates = groupAnalyzer.getDeletionCandidates(); if (isFullSync && allowDeletions && !deletionCandidates.isEmpty()) { // Batch 7 Authority Deletion BatchProcessor<String> authorityDeletionProcessor = new BatchProcessor<String>( SyncProcess.AUTHORITY_DELETION.getTitle(zone), this.transactionService.getRetryingTransactionHelper(), deletionCandidates, this.workerThreads, 10, this.applicationEventPublisher, CustomChainingUserRegistrySynchronizer.logger, this.loggingInterval); class AuthorityDeleter extends BaseBatchProcessWorker<String> { private int personProcessedCount; private int groupProcessedCount; public int getPersonProcessedCount() { return this.personProcessedCount; } public int getGroupProcessedCount() { return this.groupProcessedCount; } public String getIdentifier(String entry) { return entry; } public void process(String authority) throws Throwable { if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) { if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { CustomChainingUserRegistrySynchronizer.logger .debug("Deleting user '" + authority + "'"); } CustomChainingUserRegistrySynchronizer.this.personService.deletePerson(authority); synchronized (this) { this.personProcessedCount++; } } else { if (CustomChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { CustomChainingUserRegistrySynchronizer.logger.debug("Deleting group '" + CustomChainingUserRegistrySynchronizer.this.authorityService .getShortName(authority) + "'"); } CustomChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(authority); synchronized (this) { this.groupProcessedCount++; } } } } AuthorityDeleter authorityDeleter = new AuthorityDeleter(); authorityDeletionProcessor.process(authorityDeleter, splitTxns); groupProcessedCount += authorityDeleter.getGroupProcessedCount(); personProcessedCount += authorityDeleter.getPersonProcessedCount(); } // Remember we have visited this zone visitedZoneIds.add(zoneId); Object statusParams[] = { personProcessedCount, groupProcessedCount }; final String statusMessage = I18NUtil.getMessage("synchronization.summary.status", statusParams); if (CustomChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { CustomChainingUserRegistrySynchronizer.logger .info("Finished synchronizing users and groups with user registry '" + zone + "'"); CustomChainingUserRegistrySynchronizer.logger.info(statusMessage); } notifySyncDirectoryEnd(zone, statusMessage); }
From source file:com.rapidminer.gui.new_plotter.gui.ColorSchemeDialog.java
private void createPreviewPlotBackend(Color background, int groupinBins) { DataTable dataTable;//from w ww. ja v a 2 s .c om // retrieve data for showing example data try { ExampleSet exampleSet = (ExampleSet) ((IOObjectEntry) new RepositoryLocation("//Samples/data/Iris") .locateEntry()).retrieveData(null); dataTable = new DataTableExampleSetAdapter(exampleSet, null); } catch (MalformedRepositoryLocationException e) { return; } catch (RepositoryException e) { return; } if (dataTable == null || dataTable.getColumnNumber() < 2) { return; } // domain and y column DataTableColumn domainColumn = new DataTableColumn(dataTable, 0); DataTableColumn mainColumn = new DataTableColumn(dataTable, 1); Font titleFont = new Font("Lucida Sans", Font.PLAIN, 12); // configure gradient preview plot gradientPlotConfig = new PlotConfiguration(domainColumn); gradientPlotConfig.setTitleText(I18N .getGUILabel("plotter.configuration_dialog.color_scheme_dialog.numerical_gradient_preview.label")); gradientPlotConfig.setFrameBackgroundColor(background); gradientPlotConfig.getDomainConfigManager().setLabel(""); gradientPlotConfig.setTitleFont(titleFont); gradientPlotConfig.getLegendConfiguration().setLegendPosition(LegendPosition.NONE); RangeAxisConfig rangeAxis = new RangeAxisConfig("", gradientPlotConfig); ValueSource valueSource = new ValueSource(gradientPlotConfig, mainColumn, null, false); rangeAxis.addValueSource(valueSource, gradientPlotConfig.getAutomaticSeriesFormatForNextValueSource(rangeAxis)); gradientPlotConfig.addRangeAxisConfig(rangeAxis); DefaultDimensionConfig colorDimension = new DefaultDimensionConfig(gradientPlotConfig, mainColumn, PlotDimension.COLOR); gradientPlotConfig.setDimensionConfig(PlotDimension.COLOR, colorDimension); PlotInstance plotInstance = new PlotInstance(gradientPlotConfig, dataTable); gradientPlotter = new JFreeChartPlotEngine(plotInstance, true); // configure nominal preview plot nominalPlotConfig = new PlotConfiguration(domainColumn); nominalPlotConfig.setTitleText( I18N.getGUILabel("plotter.configuration_dialog.color_scheme_dialog.nominal_color_preview.label")); nominalPlotConfig.setFrameBackgroundColor(background); nominalPlotConfig.getDomainConfigManager().setLabel(""); nominalPlotConfig.setTitleFont(titleFont); nominalPlotConfig.getLegendConfiguration().setLegendPosition(LegendPosition.NONE); EqualDataFractionGrouping edfg; try { edfg = new EqualDataFractionGrouping(domainColumn, 4, true, DateFormat.getDateTimeInstance()); } catch (ChartConfigurationException e1) { return; } nominalPlotConfig.getDomainConfigManager().setGrouping(edfg); RangeAxisConfig nominalRangeAxis = new RangeAxisConfig("", nominalPlotConfig); ValueSource nominalValueSource = new ValueSource(nominalPlotConfig, mainColumn, AggregationFunctionType.count, true); nominalValueSource.getSeriesFormat().setSeriesType(VisualizationType.BARS); nominalValueSource.getSeriesFormat().setStackingMode(StackingMode.RELATIVE); nominalRangeAxis.addValueSource(nominalValueSource, nominalPlotConfig.getAutomaticSeriesFormatForNextValueSource(nominalRangeAxis)); nominalPlotConfig.addRangeAxisConfig(nominalRangeAxis); DefaultDimensionConfig nominalColorDimension = new DefaultDimensionConfig(nominalPlotConfig, mainColumn, PlotDimension.COLOR); EqualDataFractionGrouping edfgColor; try { edfgColor = new EqualDataFractionGrouping(mainColumn, groupinBins, true, DateFormat.getDateTimeInstance()); } catch (ChartConfigurationException e1) { return; } nominalColorDimension.setGrouping(edfgColor); nominalPlotConfig.setDimensionConfig(PlotDimension.COLOR, nominalColorDimension); PlotInstance nominalPlotInstance = new PlotInstance(nominalPlotConfig, dataTable); nominalPlotter = new JFreeChartPlotEngine(nominalPlotInstance, true); gradientPlotter.endInitializing(); nominalPlotter.endInitializing(); return; }
From source file:com.f8full.casserolesencours.CasserolesEnCoursActivity.java
private void createAndShareRequestTable() throws JSONException, HttpResponseException, IOException { String SqlQuery = "CREATE TABLE " + getString(R.string.registerRequestTableName) + " (Date:DATETIME, RequestedViewOnMasterTable_ID:STRING)"; String encodedQuery = URLEncoder.encode(SqlQuery, "UTF-8"); GoogleUrl GUrl = new GoogleUrl(SERVICE_URL + "?sql=" + encodedQuery + "&encid=true"); try {/*from w w w . jav a 2 s. co m*/ HttpRequest request = mGOOGClient.getRequestFactory().buildPostRequest(GUrl, null); HttpHeaders headers = new HttpHeaders(); headers.setContentLength("0");//Required so that Fusion Table API considers request request.setHeaders(headers); HttpResponse response = request.execute(); if (response.getStatusCode() == 200) { //Table created, insert relevant data //Extract encrypted ID String tableName = "NONAME"; InputStreamReader inputStreamReader = new InputStreamReader(response.getContent()); BufferedReader bufferedStreamReader = new BufferedReader(inputStreamReader); CSVReader reader = new CSVReader(bufferedStreamReader); // The first line is the column names, and the remaining lines are the rows. List<String[]> csvLines = reader.readAll(); List<String> columns = Arrays.asList(csvLines.get(0)); List<String[]> rows = csvLines.subList(1, csvLines.size()); //TextView textView = (TextView) findViewById(R.id.nameField); String regRequestTableIDToShare = rows.get(0)[0]; setRegRequestTableID(regRequestTableIDToShare); mRegisterRequestTableID = regRequestTableIDToShare; //Now insert data SqlQuery = "INSERT INTO " + regRequestTableIDToShare + " (Date, RequestedViewOnMasterTable_ID) VALUES ('" + DateFormat.getDateTimeInstance().format(new Date()) + "', '" + getString(R.string.regTableReqRegisteredTextStart) + " " + getString(R.string.updateRegStatusButtonText) + " " + getString(R.string.regTableReqRegisteredTextEnd) + "')"; encodedQuery = URLEncoder.encode(SqlQuery, "UTF-8"); GUrl = new GoogleUrl(SERVICE_URL + "?sql=" + encodedQuery); try { HttpRequest requestFillRegTable = mGOOGClient.getRequestFactory().buildPostRequest(GUrl, null); headers = new HttpHeaders(); headers.setContentLength("0");//Required so that Fusion Table API considers request requestFillRegTable.setHeaders(headers); HttpResponse responseFillRegTable = requestFillRegTable.execute(); if (responseFillRegTable.getStatusCode() == 200) { toastMessage("Request table timestamped :)"); } } catch (HttpResponseException e) { throw e; } catch (IOException e) { throw e; } //now share it with user casserolesencours@gmail.com try { // <entry xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl='http://schemas.google.com/acl/2007'> // <category scheme='http://schemas.google.com/g/2005#kind' // term='http://schemas.google.com/acl/2007#accessRule'/> // <gAcl:role value='writer'/> // <gAcl:scope type='user' value='new_writer@example.com'/> // </entry> XmlNamespaceDictionary docDic = new XmlNamespaceDictionary(); docDic.set("", "http://www.w3.org/2005/Atom"); docDic.set("gAcl", "http://schemas.google.com/acl/2007"); GenericData data = new GenericData(); AtomCategory category = AtomCategory.newKind("accessRule"); AtomRole role = AtomRole.newRole("writer"); AtomScope scope = AtomScope.newScope("user", "casserolesencours@gmail.com"); data.put("category", category); data.put("gAcl:role", role); data.put("gAcl:scope", scope); AtomContent content = AtomContent.forEntry(docDic, data); GUrl = new GoogleUrl("https://docs.google.com/feeds/default/private/full/" + regRequestTableIDToShare + "/acl?v=3&send-notification-emails=false"); HttpRequest requestShare = mGOOGClient.getRequestFactory().buildPostRequest(GUrl, content); HttpResponse responseShare = requestShare.execute(); if (responseShare.getStatusCode() == 201) { toastMessage(getString(R.string.registerShareTableOKToast)); mMainHandler.post(new Runnable() { public void run() { ((TextView) findViewById(R.id.geolocationStatus)) .setTextColor(getResources().getColor(R.color.text_orange)); ((TextView) findViewById(R.id.geolocationStatus)) .setText(getString(R.string.geolocationAnonymizePending)); setTableStatus(getString(R.string.geolocationAnonymizePending)); ((Button) findViewById(R.id.registerAnonymize)).setVisibility(View.GONE); ((Button) findViewById(R.id.checkAnonymize)).setVisibility(View.VISIBLE); } }); } } catch (HttpResponseException e) { if (e.getStatusCode() == 409) //Conflict { toastMessage("SHOULD NOT HAPPEN"); } throw (e); } catch (IOException e) { throw (e); } } } catch (HttpResponseException e) { throw e; } catch (IOException e) { throw e; } }
From source file:org.apache.hadoop.dfs.Balancer.java
/** main method of Balancer * @param args arguments to a Balancer//from w w w . j a v a2 s . c om * @exception any exception occurs during datanode balancing */ public int run(String[] args) throws Exception { long startTime = FSNamesystem.now(); OutputStream out = null; try { // initialize a balancer init(parseArgs(args)); /* Check if there is another balancer running. * Exit if there is another one running. */ out = checkAndMarkRunningBalancer(); if (out == null) { System.out.println("Another balancer is running. Exiting..."); return ALREADY_RUNNING; } Formatter formatter = new Formatter(System.out); System.out.println( "Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved"); int iterations = 0; while (true) { /* get all live datanodes of a cluster and their disk usage * decide the number of bytes need to be moved */ long bytesLeftToMove = initNodes(); if (bytesLeftToMove == 0) { System.out.println("The cluster is balanced. Exiting..."); return SUCCESS; } else { LOG.info("Need to move " + FsShell.byteDesc(bytesLeftToMove) + " bytes to make the cluster balanced."); } /* Decide all the nodes that will participate in the block move and * the number of bytes that need to be moved from one node to another * in this iteration. Maximum bytes to be moved per node is * Min(1 Band worth of bytes, MAX_SIZE_TO_MOVE). */ long bytesToMove = chooseNodes(); if (bytesToMove == 0) { System.out.println("No block can be moved. Exiting..."); return NO_MOVE_BLOCK; } else { LOG.info("Will move " + FsShell.byteDesc(bytesToMove) + "bytes in this iteration"); } formatter.format("%-24s %10d %19s %18s %17s\n", DateFormat.getDateTimeInstance().format(new Date()), iterations, FsShell.byteDesc(bytesMoved.get()), FsShell.byteDesc(bytesLeftToMove), FsShell.byteDesc(bytesToMove)); /* For each pair of <source, target>, start a thread that repeatedly * decide a block to be moved and its proxy source, * then initiates the move until all bytes are moved or no more block * available to move. * Exit no byte has been moved for 5 consecutive iterations. */ if (dispatchBlockMoves() > 0) { notChangedIterations = 0; } else { notChangedIterations++; if (notChangedIterations >= 5) { System.out.println("No block has been moved for 5 iterations. Exiting..."); return NO_MOVE_PROGRESS; } } // clean all lists resetData(); try { Thread.sleep(2 * conf.getLong("dfs.heartbeat.interval", 3)); } catch (InterruptedException ignored) { } iterations++; } } catch (IllegalArgumentException ae) { return ILLEGAL_ARGS; } catch (IOException e) { System.out.println("Received an IO exception: " + e.getMessage() + " . Exiting..."); return IO_EXCEPTION; } finally { // shutdown thread pools dispatcherExecutor.shutdownNow(); moverExecutor.shutdownNow(); // close the output file IOUtils.closeStream(out); try { fs.delete(BALANCER_ID_PATH, true); } catch (IOException ignored) { } System.out.println("Balancing took " + time2Str(FSNamesystem.now() - startTime)); } }
From source file:edu.ku.brc.specify.datamodel.busrules.BaseTreeBusRules.java
/** * @return true if locks were aquired.// w w w . ja v a 2 s .c om * * Locks necessary tables prior to a save. * Only used when ALLOW_CONCURRENT_FORM_ACCESS is true. */ protected boolean getRequiredLocks(Object dataObj) { TreeDefIface<?, ?, ?> treeDef = ((Treeable<?, ?, ?>) dataObj).getDefinition(); boolean result = !TreeDefStatusMgr.isRenumberingNodes(treeDef) && TreeDefStatusMgr.isNodeNumbersAreUpToDate(treeDef); if (!result) { try { Thread.sleep(1500); result = !TreeDefStatusMgr.isRenumberingNodes(treeDef) && TreeDefStatusMgr.isNodeNumbersAreUpToDate(treeDef); } catch (Exception e) { result = false; } } if (result) { TaskSemaphoreMgr.USER_ACTION r = TaskSemaphoreMgr.lock(getFormSaveLockTitle(), getFormSaveLockName(), "save", TaskSemaphoreMgr.SCOPE.Discipline, false, new TaskSemaphoreMgrCallerIFace() { /* (non-Javadoc) * @see edu.ku.brc.specify.dbsupport.TaskSemaphoreMgrCallerIFace#resolveConflict(edu.ku.brc.specify.datamodel.SpTaskSemaphore, boolean, java.lang.String) */ @Override public USER_ACTION resolveConflict(SpTaskSemaphore semaphore, boolean previouslyLocked, String prevLockBy) { if (System.currentTimeMillis() - semaphore.getLockedTime().getTime() > FORM_SAVE_LOCK_MAX_DURATION_IN_MILLIS) { //something is clearly wrong with the lock. Ignore it and re-use it. It will be cleared when save succeeds. log.warn("automatically overriding expired " + getFormSaveLockTitle() + " lock set by " + prevLockBy + " at " + DateFormat.getDateTimeInstance().format(semaphore.getLockedTime())); return USER_ACTION.OK; } else { return USER_ACTION.Error; } } }, false); result = r == TaskSemaphoreMgr.USER_ACTION.OK; } return result; }
From source file:org.apache.hadoop.hdfs.server.balancer.Balancer.java
/** main method of Balancer * @param args arguments to a Balancer/*from w ww . j a v a2 s .c o m*/ * @exception any exception occurs during datanode balancing */ public int run(String[] args) throws Exception { long startTime = Util.now(); OutputStream out = null; try { // initialize a balancer init(parseArgs(args)); /* Check if there is another balancer running. * Exit if there is another one running. */ out = checkAndMarkRunningBalancer(); if (out == null) { System.out.println("Another balancer is running. Exiting..."); return ALREADY_RUNNING; } Formatter formatter = new Formatter(System.out); System.out.println( "Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved"); int iterations = 0; while (true) { /* get all live datanodes of a cluster and their disk usage * decide the number of bytes need to be moved */ long bytesLeftToMove = initNodes(); if (bytesLeftToMove == 0) { System.out.println("The cluster is balanced. Exiting..."); return SUCCESS; } else { LOG.info("Need to move " + StringUtils.byteDesc(bytesLeftToMove) + " bytes to make the cluster balanced."); } /* Decide all the nodes that will participate in the block move and * the number of bytes that need to be moved from one node to another * in this iteration. Maximum bytes to be moved per node is * Min(1 Band worth of bytes, MAX_SIZE_TO_MOVE). */ long bytesToMove = chooseNodes(); if (bytesToMove == 0) { System.out.println("No block can be moved. Exiting..."); return NO_MOVE_BLOCK; } else { LOG.info("Will move " + StringUtils.byteDesc(bytesToMove) + "bytes in this iteration"); } formatter.format("%-24s %10d %19s %18s %17s\n", DateFormat.getDateTimeInstance().format(new Date()), iterations, StringUtils.byteDesc(bytesMoved.get()), StringUtils.byteDesc(bytesLeftToMove), StringUtils.byteDesc(bytesToMove)); /* For each pair of <source, target>, start a thread that repeatedly * decide a block to be moved and its proxy source, * then initiates the move until all bytes are moved or no more block * available to move. * Exit no byte has been moved for 5 consecutive iterations. */ if (dispatchBlockMoves() > 0) { notChangedIterations = 0; } else { notChangedIterations++; if (notChangedIterations >= 5) { System.out.println("No block has been moved for 5 iterations. Exiting..."); return NO_MOVE_PROGRESS; } } // clean all lists resetData(); try { Thread.sleep(2 * conf.getLong("dfs.heartbeat.interval", 3)); } catch (InterruptedException ignored) { } iterations++; } } catch (IllegalArgumentException ae) { return ILLEGAL_ARGS; } catch (IOException e) { System.out.println("Received an IO exception: " + e.getMessage() + " . Exiting..."); return IO_EXCEPTION; } finally { // shutdown thread pools dispatcherExecutor.shutdownNow(); moverExecutor.shutdownNow(); shouldRun = false; try { if (keyupdaterthread != null) keyupdaterthread.interrupt(); } catch (Exception e) { LOG.warn("Exception shutting down access key updater thread", e); } // close the output file IOUtils.closeStream(out); if (fs != null) { try { fs.delete(BALANCER_ID_PATH, true); } catch (IOException ignored) { } } System.out.println("Balancing took " + time2Str(Util.now() - startTime)); } }
From source file:com.f8full.casserolesencours.CasserolesEnCoursActivity.java
protected void writeToFusionTable(boolean manual, String desc) { if (mAlohar.getPlaceManager().getCurrentLocation().getLatitude() == 0.0 || mAlohar.getPlaceManager().getCurrentLocation().getLongitude() == 0.0) { toastMessage(getString(R.string.nullocationErrorMessage)); return;/* ww w .ja v a2 s . c om*/ } JSONObject newData = new JSONObject(); try { newData.put("DESC", desc); newData.put("LOCATION", getLatLongPosition()); newData.put("DATE", DateFormat.getDateTimeInstance().format(new Date())); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } writeToFusionTable(manual, newData); }
From source file:mzb.Balancer.java
/** Run an iteration for all datanodes. */ private ReturnStatus run(int iteration, Formatter formatter, Configuration conf) { try {//from ww w. j a v a2s. com this.fs = FileSystem.get(conf); /* get all live datanodes of a cluster and their disk usage * decide the number of bytes need to be moved */ //final long bytesLeftToMove = initNodes(nnc.client.getDatanodeReport(DatanodeReportType.LIVE)); /*if (bytesLeftToMove == 0) { System.out.println("The cluster is balanced. Exiting..."); return ReturnStatus.SUCCESS; } else { LOG.info( "Need to move "+ StringUtils.byteDesc(bytesLeftToMove) + " to make the cluster balanced." ); }*/ /* Decide all the nodes that will participate in the block move and * the number of bytes that need to be moved from one node to another * in this iteration. Maximum bytes to be moved per node is * Min(1 Band worth of bytes, MAX_SIZE_TO_MOVE). */ final long bytesToMove = chooseNodes(metaFile, targetDir); if (bytesToMove == 0) { System.out.println("No block can be moved. Exiting..."); return ReturnStatus.NO_MOVE_BLOCK; } else { LOG.info("Will move " + StringUtils.byteDesc(bytesToMove) + " in this iteration"); } formatter.format("%-24s %10d %19s %18s %n", DateFormat.getDateTimeInstance().format(new Date()), iteration, StringUtils.byteDesc(bytesMoved.get()), //StringUtils.byteDesc(bytesLeftToMove), StringUtils.byteDesc(bytesToMove)); /* For each pair of <source, target>, start a thread that repeatedly * decide a block to be moved and its proxy source, * then initiates the move until all bytes are moved or no more block * available to move. * Exit no byte has been moved for 5 consecutive iterations. */ if (!this.nnc.shouldContinue(dispatchBlockMoves())) { return ReturnStatus.NO_MOVE_PROGRESS; } return ReturnStatus.IN_PROGRESS; } catch (IllegalArgumentException e) { System.out.println(e + ". Exiting ..."); return ReturnStatus.ILLEGAL_ARGS; } catch (IOException e) { System.out.println(e + ". Exiting ..."); return ReturnStatus.IO_EXCEPTION; } catch (InterruptedException e) { System.out.println(e + ". Exiting ..."); return ReturnStatus.INTERRUPTED; } finally { // shutdown thread pools dispatcherExecutor.shutdownNow(); moverExecutor.shutdownNow(); } }