mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	125606 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
      125515 slanglois: MNT-16155 Update source headers - add new Copyrights for Java and JSP source files + automatic check in the build
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125788 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			569 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			569 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
/*
 | 
						|
 * #%L
 | 
						|
 * Alfresco Repository
 | 
						|
 * %%
 | 
						|
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | 
						|
 * %%
 | 
						|
 * This file is part of the Alfresco software. 
 | 
						|
 * If the software was purchased under a paid Alfresco license, the terms of 
 | 
						|
 * the paid license agreement will prevail.  Otherwise, the software is 
 | 
						|
 * provided under the following open source license terms:
 | 
						|
 * 
 | 
						|
 * Alfresco is free software: you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU Lesser General Public License as published by
 | 
						|
 * the Free Software Foundation, either version 3 of the License, or
 | 
						|
 * (at your option) any later version.
 | 
						|
 * 
 | 
						|
 * Alfresco is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU Lesser General Public License for more details.
 | 
						|
 * 
 | 
						|
 * You should have received a copy of the GNU Lesser General Public License
 | 
						|
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 * #L%
 | 
						|
 */
 | 
						|
package org.alfresco.tools;
 | 
						|
 | 
						|
import java.io.BufferedReader;
 | 
						|
import java.io.File;
 | 
						|
import java.io.FileInputStream;
 | 
						|
import java.io.IOException;
 | 
						|
import java.io.InputStreamReader;
 | 
						|
import java.nio.charset.Charset;
 | 
						|
import java.nio.charset.IllegalCharsetNameException;
 | 
						|
import java.nio.charset.UnsupportedCharsetException;
 | 
						|
import java.util.ArrayList;
 | 
						|
import java.util.Collection;
 | 
						|
import java.util.Collections;
 | 
						|
import java.util.HashSet;
 | 
						|
import java.util.Iterator;
 | 
						|
import java.util.List;
 | 
						|
import java.util.Set;
 | 
						|
import java.util.concurrent.atomic.AtomicInteger;
 | 
						|
 | 
						|
import org.alfresco.model.ContentModel;
 | 
						|
import org.alfresco.repo.batch.BatchProcessWorkProvider;
 | 
						|
import org.alfresco.repo.batch.BatchProcessor;
 | 
						|
import org.alfresco.repo.batch.BatchProcessor.BatchProcessWorker;
 | 
						|
import org.alfresco.repo.batch.BatchProcessor.BatchProcessWorkerAdaptor;
 | 
						|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
 | 
						|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
 | 
						|
import org.alfresco.repo.security.person.PersonServiceImpl;
 | 
						|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
 | 
						|
import org.alfresco.service.cmr.repository.NodeRef;
 | 
						|
import org.alfresco.service.cmr.repository.NodeService;
 | 
						|
import org.alfresco.service.cmr.security.NoSuchPersonException;
 | 
						|
import org.alfresco.service.cmr.security.PersonService;
 | 
						|
import org.alfresco.service.transaction.TransactionService;
 | 
						|
import org.alfresco.util.VmShutdownListener;
 | 
						|
import org.apache.commons.logging.Log;
 | 
						|
import org.apache.commons.logging.LogFactory;
 | 
						|
 | 
						|
/**
 | 
						|
 * Rename user tool. This tool provides minimal support for renaming users.
 | 
						|
 * See {@link #displayHelp} message for restrictions.
 | 
						|
 * <pre>
 | 
						|
 * Usage: renameUser -user username [options] oldUsername newUsername");
 | 
						|
 *        renameUser -user username [options] -file filename");
 | 
						|
 * </pre>
 | 
						|
 * The csv file has a simple comma separated list, with
 | 
						|
 * a pair of usernames on each line. Comments and blank
 | 
						|
 * lines may also be included. For example:
 | 
						|
 * <pre>
 | 
						|
 * # List of usernames to change
 | 
						|
 * 
 | 
						|
 * # oldUsername,newUsername
 | 
						|
 * johnp,ceo # President and CEO
 | 
						|
 * johnn,cto # CTO and Chairman
 | 
						|
 * </pre>
 | 
						|
 * 
 | 
						|
 * @author Alan Davis
 | 
						|
 */
 | 
						|
public class RenameUser extends Tool
 | 
						|
{
 | 
						|
    private static Log logger = LogFactory.getLog(RenameUser.class);
 | 
						|
    
 | 
						|
    /** User Rename Tool Context */
 | 
						|
    protected RenameUserToolContext context;
 | 
						|
    private boolean login = true;
 | 
						|
    
 | 
						|
    PersonService personService;
 | 
						|
    NodeService nodeService;
 | 
						|
 | 
						|
    private PersonService getPersonService()
 | 
						|
    {
 | 
						|
        if (personService == null)
 | 
						|
        {
 | 
						|
            personService = getServiceRegistry().getPersonService();
 | 
						|
        }
 | 
						|
        return personService;
 | 
						|
    }
 | 
						|
 | 
						|
    private NodeService getNodeService()
 | 
						|
    {
 | 
						|
        if (nodeService == null)
 | 
						|
        {
 | 
						|
            nodeService = getServiceRegistry().getNodeService();
 | 
						|
        }
 | 
						|
        return nodeService;
 | 
						|
    }
 | 
						|
    
 | 
						|
    public void setLogin(boolean login)
 | 
						|
    {
 | 
						|
        this.login = login;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Entry Point
 | 
						|
     * 
 | 
						|
     * @param args
 | 
						|
     */
 | 
						|
    public static void main(String[] args)
 | 
						|
    {
 | 
						|
        Tool tool = new RenameUser();
 | 
						|
        tool.start(args);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * (non-Javadoc)
 | 
						|
     * @see org.alfresco.tools.Tool#processArgs(java.lang.String[])
 | 
						|
     */
 | 
						|
    @Override
 | 
						|
    protected ToolContext processArgs(String[] args)
 | 
						|
        throws ToolArgumentException
 | 
						|
    {
 | 
						|
        context = new RenameUserToolContext();
 | 
						|
        context.setLogin(login);
 | 
						|
 | 
						|
        int i = 0;
 | 
						|
        while (i < args.length)
 | 
						|
        {
 | 
						|
            if (args[i].equals("-h") || args[i].equals("-help"))
 | 
						|
            {
 | 
						|
                context.setHelp(true);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            else if (args[i].equals("-user"))
 | 
						|
            {
 | 
						|
                i++;
 | 
						|
                if (i == args.length || args[i].length() == 0)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("The value <user> for the option -user must be specified");
 | 
						|
                }
 | 
						|
                context.setUsername(args[i]);
 | 
						|
            }
 | 
						|
            else if (args[i].equals("-pwd"))
 | 
						|
            {
 | 
						|
                i++;
 | 
						|
                if (i == args.length || args[i].length() == 0)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("The value <password> for the option -pwd must be specified");
 | 
						|
                }
 | 
						|
                context.setPassword(args[i]);
 | 
						|
            }
 | 
						|
            else if (args[i].equals("-encoding"))
 | 
						|
            {
 | 
						|
                i++;
 | 
						|
                if (i == args.length || args[i].length() == 0)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("The value <encoding> for the option -encoding must be specified");
 | 
						|
                }
 | 
						|
                try
 | 
						|
                {
 | 
						|
                    context.encoding = Charset.forName(args[i]);
 | 
						|
                }
 | 
						|
                catch (IllegalCharsetNameException e)
 | 
						|
                { 
 | 
						|
                    throw new ToolArgumentException("The value <encoding> is not recognised");
 | 
						|
                }
 | 
						|
                catch (UnsupportedCharsetException e)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("The value <encoding> is unsupported");
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else if (args[i].equals("-quiet"))
 | 
						|
            {
 | 
						|
                context.setQuiet(true);
 | 
						|
            }
 | 
						|
            else if (args[i].equals("-verbose"))
 | 
						|
            {
 | 
						|
                context.setVerbose(true);
 | 
						|
            }
 | 
						|
            else if (args[i].equals("-f") || args[i].equals("-file"))
 | 
						|
            {
 | 
						|
                i++;
 | 
						|
                if (i == args.length || args[i].length() == 0)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("The value <filename> for the option -file must be specified");
 | 
						|
                }
 | 
						|
                context.setFilename(args[i]);
 | 
						|
            }
 | 
						|
            else if (!args[i].startsWith("-"))
 | 
						|
            {
 | 
						|
                i++;
 | 
						|
                if (i == args.length || args[i-1].trim().length() == 0 || args[i].trim().length() == 0)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("Both <oldUsername> <newUsername> must be specified");
 | 
						|
                }
 | 
						|
                if (context.userCount() > 0)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("Only one <oldUsername> <newUsername> pair may be " +
 | 
						|
                    		"specified on the command line. See the -file option");
 | 
						|
                }
 | 
						|
                String oldUsername = args[i-1].trim();
 | 
						|
                String newUsername = args[i].trim();
 | 
						|
                String error = context.add(-1, null, oldUsername, newUsername);
 | 
						|
                if (error != null)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException(error);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                throw new ToolArgumentException("Unknown option " + args[i]);
 | 
						|
            }
 | 
						|
 | 
						|
            // next argument
 | 
						|
            i++;
 | 
						|
        }
 | 
						|
 | 
						|
        return context;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /* (non-Javadoc)
 | 
						|
     * @see org.alfresco.tools.Tool#displayHelp()
 | 
						|
     */
 | 
						|
    protected @Override
 | 
						|
    /*package*/ void displayHelp()
 | 
						|
    {
 | 
						|
        logError("This tool provides minimal support for renaming users. It fixes");
 | 
						|
        logError("authorities, group memberships and current zone (older versions");
 | 
						|
        logError("still require a property change).");
 | 
						|
        logError("");
 | 
						|
        logError("WARNING: It does NOT change properties that store the username such");
 | 
						|
        logError("         as (creator, modifier, lock owner or owner). Of these owner");
 | 
						|
        logError("         and lock affect user rights. The username is also used");
 | 
						|
        logError("         directly in workflow, for RM caveats, for Share invites and");
 | 
						|
        logError("         auditing");
 | 
						|
        logError("");
 | 
						|
        logError("Usage: renameUser -user username [options] oldUsername newUsername");
 | 
						|
        logError("       renameUser -user username [options] -file filename");
 | 
						|
        logError("");
 | 
						|
        logError("   username: username for login");
 | 
						|
        logError("oldUsername: current username ");
 | 
						|
        logError("newUsername: replacement username ");
 | 
						|
        logError("");
 | 
						|
        logError("Options:");
 | 
						|
        logError(" -h[elp] display this help");
 | 
						|
        logError(" -pwd password for login");
 | 
						|
        logError(" -f[ile] csv file of old and new usernames");
 | 
						|
        logError(" -encoding for source file (default: " + Charset.defaultCharset() + ")");
 | 
						|
        logError(" -quiet do not display any messages during rename");
 | 
						|
        logError(" -verbose report rename progress");
 | 
						|
    }
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * (non-Javadoc)
 | 
						|
     * @see org.alfresco.tools.Tool#getToolName()
 | 
						|
     */
 | 
						|
    @Override
 | 
						|
    protected String getToolName()
 | 
						|
    {
 | 
						|
        return "Alfresco Rename User";
 | 
						|
    }
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * (non-Javadoc)
 | 
						|
     * @see org.alfresco.tools.Tool#execute()
 | 
						|
     */
 | 
						|
    @Override
 | 
						|
    protected int execute() throws ToolException
 | 
						|
    {
 | 
						|
        // Used for ability to be final and have a set
 | 
						|
        final AtomicInteger status = new AtomicInteger(0);
 | 
						|
 | 
						|
        BatchProcessWorker<User> worker = new BatchProcessWorkerAdaptor<User>()
 | 
						|
        {
 | 
						|
            public void process(final User user) throws Throwable
 | 
						|
            {
 | 
						|
                RunAsWork<Void> runAsWork = new RunAsWork<Void>()
 | 
						|
                {
 | 
						|
                    @Override
 | 
						|
                    public Void doWork() throws Exception
 | 
						|
                    {
 | 
						|
                        try
 | 
						|
                        {
 | 
						|
                            renameUser(user.getOldUsername(), user.getNewUsername());
 | 
						|
                        }
 | 
						|
                        catch (Throwable t)
 | 
						|
                        {
 | 
						|
                            status.set(handleError(t));
 | 
						|
                        }
 | 
						|
                        return null;
 | 
						|
                    }
 | 
						|
                };
 | 
						|
                AuthenticationUtil.runAs(runAsWork, context.getUsername());
 | 
						|
            }
 | 
						|
        };
 | 
						|
        
 | 
						|
        // Use 2 threads, 20 User objects per transaction. Log every 100 entries.
 | 
						|
        BatchProcessor<User> processor = new BatchProcessor<User>(
 | 
						|
                "HomeFolderProviderSynchronizer",
 | 
						|
                getServiceRegistry().getTransactionService().getRetryingTransactionHelper(),
 | 
						|
                new WorkProvider(context),
 | 
						|
                2, 20,
 | 
						|
                null,
 | 
						|
                logger, 100);
 | 
						|
        processor.process(worker, true);
 | 
						|
 | 
						|
        return status.get();
 | 
						|
    }
 | 
						|
    
 | 
						|
    private void renameUser(String oldUsername, String newUsername)
 | 
						|
    {
 | 
						|
        logInfo("\""+oldUsername+"\" --> \""+newUsername+"\""); 
 | 
						|
        try
 | 
						|
        {
 | 
						|
            NodeRef person = getPersonService().getPerson(oldUsername, false);
 | 
						|
            
 | 
						|
            // Allow us to update the username just like the LDAP process
 | 
						|
            AlfrescoTransactionSupport.bindResource(PersonServiceImpl.KEY_ALLOW_UID_UPDATE, Boolean.TRUE);
 | 
						|
 | 
						|
            // Update the username property which will result in a PersonServiceImpl.onUpdateProperties call
 | 
						|
            // on commit.
 | 
						|
            getNodeService().setProperty(person, ContentModel.PROP_USERNAME, newUsername);
 | 
						|
        }
 | 
						|
        catch (NoSuchPersonException e)
 | 
						|
        {
 | 
						|
            logError("User does not exist: "+oldUsername);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    public class User
 | 
						|
    {
 | 
						|
        private final String oldUsername;
 | 
						|
        private final String newUsername;
 | 
						|
        
 | 
						|
        public User(String oldUsername, String newUsername)
 | 
						|
        {
 | 
						|
            this.oldUsername = oldUsername;
 | 
						|
            this.newUsername = newUsername;
 | 
						|
        }
 | 
						|
 | 
						|
        public String getOldUsername()
 | 
						|
        {
 | 
						|
            return oldUsername;
 | 
						|
        }
 | 
						|
 | 
						|
        public String getNewUsername()
 | 
						|
        {
 | 
						|
            return newUsername;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    public class RenameUserToolContext extends ToolContext
 | 
						|
    {
 | 
						|
        /**
 | 
						|
         * Old and new usernames to change.
 | 
						|
         */
 | 
						|
        private List<User> usernames = new ArrayList<User>();
 | 
						|
        
 | 
						|
        // Internal - used check the name has not been used before.
 | 
						|
        private Set<String> uniqueNames = new HashSet<String>();
 | 
						|
        
 | 
						|
        /**
 | 
						|
         * Source filename of usernames.
 | 
						|
         */
 | 
						|
        private String filename;
 | 
						|
        
 | 
						|
        /**
 | 
						|
         * Encoding of filename of usernames.
 | 
						|
         */
 | 
						|
        private Charset encoding = Charset.defaultCharset();
 | 
						|
        
 | 
						|
        public void setFilename(String filename)
 | 
						|
        {
 | 
						|
            this.filename = filename;
 | 
						|
        }
 | 
						|
        
 | 
						|
        public String add(int lineNumber, String line, String oldUsername, String newUsername)
 | 
						|
        {
 | 
						|
            String error = null;
 | 
						|
            if (oldUsername.equals(newUsername))
 | 
						|
            {
 | 
						|
                error = "Old and new usernames are the same";
 | 
						|
                if (line != null)
 | 
						|
                    error = "Error on line " + lineNumber + " ("+error+"): " + line;
 | 
						|
            }
 | 
						|
            else if (uniqueNames.contains(oldUsername))
 | 
						|
            {
 | 
						|
                error = "Old username already specified";
 | 
						|
                if (line != null)
 | 
						|
                    error = "Error on line " + lineNumber + " ("+error+"): " + line;
 | 
						|
            }
 | 
						|
            else if (uniqueNames.contains(newUsername))
 | 
						|
            {
 | 
						|
                error = "New username already specified";
 | 
						|
                if (line != null)
 | 
						|
                    error = "Error on line " + lineNumber + " ("+error+"): " + line;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                add(new User(oldUsername, newUsername));
 | 
						|
            }
 | 
						|
            return error;
 | 
						|
        }
 | 
						|
 | 
						|
        private void add(User user)
 | 
						|
        {
 | 
						|
            usernames.add(user);
 | 
						|
            uniqueNames.add(user.getOldUsername());
 | 
						|
            uniqueNames.add(user.getNewUsername());
 | 
						|
        }
 | 
						|
        
 | 
						|
        public int userCount()
 | 
						|
        {
 | 
						|
            return usernames.size();
 | 
						|
        }
 | 
						|
        
 | 
						|
        public Iterator<User> iterator()
 | 
						|
        {
 | 
						|
            return usernames.iterator();
 | 
						|
        }
 | 
						|
 | 
						|
        /*
 | 
						|
         * (non-Javadoc)
 | 
						|
         * @see org.alfresco.tools.ToolContext#validate()
 | 
						|
         */
 | 
						|
        @Override
 | 
						|
        /*package*/ void validate()
 | 
						|
        {
 | 
						|
            super.validate();
 | 
						|
            
 | 
						|
            if (filename != null)
 | 
						|
            {
 | 
						|
                if (userCount() > 0)
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("<filename> should not have been specified if " +
 | 
						|
                            "<oldUsername> <newUsername> has been specified on the command line.");
 | 
						|
                }
 | 
						|
                File file = new File(filename);
 | 
						|
                if (!file.exists())
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("File " + filename + " does not exist.");
 | 
						|
                }
 | 
						|
                if (!readFile(file))
 | 
						|
                {
 | 
						|
                    throw new ToolArgumentException("File " + filename + " contained errors.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            if (userCount() == 0)
 | 
						|
            {
 | 
						|
                throw new ToolArgumentException("No old and new usernames have been specified.");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Read the user names out of the file.
 | 
						|
         * @param file to be read
 | 
						|
         * @return {@code true} if there were no problems found with the file contents.
 | 
						|
         */
 | 
						|
        private boolean readFile(File file)
 | 
						|
        {
 | 
						|
            BufferedReader in = null;
 | 
						|
            boolean noErrors = true;
 | 
						|
            try
 | 
						|
            {
 | 
						|
                in  = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding.name()));
 | 
						|
                int lineNumber = 1;
 | 
						|
                for (String line = in.readLine(); line != null; line = in.readLine(), lineNumber++)
 | 
						|
                {
 | 
						|
                    int i = line.indexOf('#');
 | 
						|
                    if (i != -1)
 | 
						|
                    {
 | 
						|
                        line = line.substring(0, i);
 | 
						|
                    }
 | 
						|
                    if (line.trim().length() != 0)
 | 
						|
                    {
 | 
						|
                        String[] names = line.split(",");
 | 
						|
                        String oldUsername = names[0].trim();
 | 
						|
                        String newUsername = names[1].trim();
 | 
						|
                        if (names.length != 2 || oldUsername.length() == 0 || newUsername.length() == 0)
 | 
						|
                        {
 | 
						|
                            RenameUser.this.logError("Error on line " + lineNumber + ": " + line);
 | 
						|
                            noErrors = false;
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            String error = context.add(lineNumber, line, oldUsername, newUsername);
 | 
						|
                            if (error != null)
 | 
						|
                            {
 | 
						|
                                RenameUser.this.logError(error);
 | 
						|
                                noErrors = false;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            catch (IOException e)
 | 
						|
            {
 | 
						|
                throw new ToolArgumentException("Failed to read <filename>.", e);
 | 
						|
            }
 | 
						|
            finally
 | 
						|
            {
 | 
						|
                if (in != null)
 | 
						|
                {
 | 
						|
                    try
 | 
						|
                    {
 | 
						|
                        in.close();
 | 
						|
                    } catch (IOException e)
 | 
						|
                    {
 | 
						|
                        // ignore
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return noErrors;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // BatchProcessWorkProvider returns batches of 100 User objects.
 | 
						|
    private class WorkProvider implements BatchProcessWorkProvider<User>
 | 
						|
    {
 | 
						|
        private static final int BATCH_SIZE = 100;
 | 
						|
        
 | 
						|
        private final VmShutdownListener vmShutdownLister = new VmShutdownListener("getRenameUserWorkProvider");
 | 
						|
        private final Iterator<User> iterator;
 | 
						|
        private final int size;
 | 
						|
        
 | 
						|
        public WorkProvider(RenameUserToolContext context)
 | 
						|
        {
 | 
						|
            iterator = context.iterator();
 | 
						|
            size = context.userCount();
 | 
						|
        }
 | 
						|
 | 
						|
        @Override
 | 
						|
        public synchronized int getTotalEstimatedWorkSize()
 | 
						|
        {
 | 
						|
            return size;
 | 
						|
        }
 | 
						|
 | 
						|
        @Override
 | 
						|
        public synchronized Collection<User> getNextWork()
 | 
						|
        {
 | 
						|
            if (vmShutdownLister.isVmShuttingDown())
 | 
						|
            {
 | 
						|
                return Collections.emptyList();
 | 
						|
            }
 | 
						|
            
 | 
						|
            Collection<User> results = new ArrayList<User>(BATCH_SIZE);
 | 
						|
            while (results.size() < BATCH_SIZE && iterator.hasNext())
 | 
						|
            {
 | 
						|
                results.add(iterator.next());
 | 
						|
            }
 | 
						|
            return results;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |