Merged V3.4-BUG-FIX to HEAD

28650: Merged DEV/TEMPORARY to V3.4-BUG-FIX
      28637: ALF-5601: WCM Reviewer should be able to modify 'Launch Date' of the review item.
         Set "wcmwf:launchDate" to read-only on "submitpendingTask".
   28697: Fix for ALF-2711 - Fix to handle incorrect (negative size!) content length headers sent by Adobe Flash when uploading files over 2GB.
   28702: Merged DEV to V3.4-BUG-FIX
      28693: ALF-9314: Unable to add to multi-valued properties via AVM Console
             The node property value of Collection type must be set within square braces
             as a comma separated values without spaces. E.g. [aaa,bbb,ccc] 
   28718: Merged PATCHES/V3.4.2 to V3.4-BUG-FIX
      28569: ALF-9253 / ALF-9166: 'A valid SecureContext was not provided in the RequestContext' exception on startup following upgrade to 3.4.1
      28618: ALF-8385 / ALF-9364: Merged DEV/TEMPORARY to PATCHES/V3.4.2
         28565: ALF-5887 Addition of RenameUser command line toolContext
            - PersonServiceImpl should not disable normal behaviour when handling duplicate Person NodeRefs as the userAuthorityCache does not get updated correctly
            - Tool (base class for Import, Export and RenameUser command line tools) should not automatically login if setLogin(false) has been called. 
   28719: Merged V3.4 to V3.4-BUG-FIX
      28648: ALF-9103: Remove obsolete (and mis-spelled) use-old-dm-alcs-context.xml.sample
      28701: Corrected library for - Fix for ALF-7860 - Regression: Close button doesn't work in Node Browser


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28721 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2011-06-30 11:36:51 +00:00
parent 404b096c44
commit eddc7efe0c
10 changed files with 915 additions and 94 deletions

View File

@@ -1,53 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="dmPermissionsDaoComponent" class="org.alfresco.repo.domain.hibernate.OldADMPermissionsDaoComponentImpl" >
<property name="aclDaoComponent">
<ref bean="aclDaoComponent" />
</property>
<property name="protocolToACLDAO">
<map>
<entry key="workspace"><ref bean="nodeACLDAO"></ref></entry>
<entry key="avm"><ref bean="avmACLDAO"/></entry>
</map>
</property>
<property name="defaultACLDAO">
<ref bean="nodeACLDAO"/>
</property>
</bean>
<bean id="nodeACLDAO" class="org.alfresco.repo.domain.hibernate.NodeAccessControlListDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="nodeDaoService">
<ref bean="nodeDaoService" />
</property>
</bean>
<bean id="patch.updateDmPermissions" class="java.util.ArrayList" />
<bean id="aclDaoComponentImpl" class="org.alfresco.repo.domain.hibernate.AclDaoComponentImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="qnameDAO">
<ref bean="qnameDAO" />
</property>
<property name="patchDAO">
<ref bean="patchDAO" />
</property>
<property name="avmNodeDAO">
<ref bean="newAvmNodeDAO" />
</property>
<property name="aclCache">
<ref bean="aclCache" />
</property>
<property name="useOldPermissions">
<value>true</value>
</property>
</bean>
</beans>

View File

@@ -58,6 +58,7 @@
<bean id="renditionDefinitionPersister" class="org.alfresco.repo.rendition.RenditionDefinitionPersisterImpl" >
<property name="runtimeActionService" ref="actionService" />
<property name="nodeService" ref="NodeService" />
<property name="behaviourFilter" ref="policyBehaviourFilter" />
</bean>
<bean id="renditionLocationResolver" class="org.alfresco.repo.rendition.StandardRenditionLocationResolverImpl" >

View File

@@ -958,7 +958,7 @@ public class AVMInterpreter
private static String[] getCSVArray(String valueString)
{
String[] elements = valueString.split(",\\s+");
String[] elements = valueString.split(",");
if (elements.length == 0)
{

View File

@@ -27,6 +27,7 @@ import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ActionModel;
import org.alfresco.repo.action.RuntimeActionService;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.CompositeAction;
import org.alfresco.service.cmr.rendition.RenditionDefinition;
@@ -59,6 +60,7 @@ public class RenditionDefinitionPersisterImpl implements RenditionDefinitionPers
/* Injected services */
private NodeService nodeService;
private RuntimeActionService runtimeActionService;
private BehaviourFilter behaviourFilter;
/**
* Injects the NodeService bean.
@@ -80,6 +82,12 @@ public class RenditionDefinitionPersisterImpl implements RenditionDefinitionPers
this.runtimeActionService = runtimeActionService;
}
public void setBehaviourFilter(BehaviourFilter behaviourFilter)
{
this.behaviourFilter = behaviourFilter;
}
public List<RenditionDefinition> loadRenditionDefinitions()
{
checkRenderingActionRootNodeExists();
@@ -148,12 +156,23 @@ public class RenditionDefinitionPersisterImpl implements RenditionDefinitionPers
{
NodeRef actionNodeRef = findOrCreateActionNode(renderingAction);
// ALF-9166 describes a problem whereby versionable saved rendition definition nodes cause problems on upgrade.
// This appears to be due to a rule defined on Company Home. The behaviour suppression below is a workaround for that issue.
try
{
behaviourFilter.disableBehaviour(actionNodeRef, ContentModel.ASPECT_VERSIONABLE);
// TODO Serialize using JSON content instead.
// The current serialization mechanism creates a complex content model
// structure which is verbose and a JSON-based approach using a simplified
// content model perhaps could offer performance improvements.
runtimeActionService.saveActionImpl(actionNodeRef, renderingAction);
}
finally
{
behaviourFilter.enableBehaviour(actionNodeRef, ContentModel.ASPECT_VERSIONABLE);
}
}
public void deleteRenditionDefinition(RenditionDefinition renderingAction)
{

View File

@@ -44,7 +44,9 @@ import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryParser;
import org.alfresco.repo.security.person.PersonServiceImpl;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -1108,7 +1110,7 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
String authAfter = DefaultTypeConverter.INSTANCE.convert(String.class, after.get(idProp));
if (!EqualsHelper.nullSafeEquals(authBefore, authAfter))
{
if (authBefore.equalsIgnoreCase(authAfter))
if (AlfrescoTransactionSupport.getResource(PersonServiceImpl.KEY_ALLOW_UID_UPDATE) != null || authBefore.equalsIgnoreCase(authAfter))
{
if (isAuthority)
{

View File

@@ -120,7 +120,7 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
private static final String SYSTEM_USAGE_WARN_LIMIT_USERS_EXCEEDED_VERBOSE = "system.usage.err.limit_users_exceeded_verbose";
private static final String KEY_POST_TXN_DUPLICATES = "PersonServiceImpl.KEY_POST_TXN_DUPLICATES";
private static final String KEY_ALLOW_UID_UPDATE = "PersonServiceImpl.KEY_ALLOW_UID_UPDATE";
public static final String KEY_ALLOW_UID_UPDATE = "PersonServiceImpl.KEY_ALLOW_UID_UPDATE";
private static final String KEY_USERS_CREATED = "PersonServiceImpl.KEY_USERS_CREATED";
private StoreRef storeRef;
@@ -603,10 +603,6 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
{
public Object execute() throws Throwable
{
try
{
policyBehaviourFilter.disableBehaviour(ContentModel.TYPE_PERSON);
if (duplicateMode.equalsIgnoreCase(SPLIT))
{
logger.info("Splitting " + postTxnDuplicates.size() + " duplicate person objects.");
@@ -627,11 +623,6 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
logger.debug("Duplicate person objects exist");
}
}
}
finally
{
policyBehaviourFilter.enableBehaviour(ContentModel.TYPE_PERSON);
}
// Done
return null;
@@ -644,7 +635,7 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
{
for (NodeRef nodeRef : toDelete)
{
nodeService.deleteNode(nodeRef);
deletePerson(nodeRef);
}
}

View File

@@ -58,6 +58,7 @@ import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.security.PersonService.PersonInfo;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.tools.RenameUser;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.GUID;
@@ -79,11 +80,6 @@ public class PersonTest extends TestCase
private MutableAuthenticationDao authenticationDAO;
private UserTransaction testTX;
public PersonTest()
{
super();
}
public void setUp() throws Exception
{
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
@@ -1388,4 +1384,79 @@ public class PersonTest extends TestCase
personService.createPerson(properties);
personService.notifyPerson(userName, "abc");
}
public void testRenameUser() throws Exception
{
// Note: RenameUserTest contains unit tests.
// End the Spring-managed txn
testTX.commit();
final String username = AuthenticationUtil.getAdminUserName();
final String oldUsername = GUID.generate();
final String newUsername = oldUsername+GUID.generate();
// Create a person
final NodeRef person = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<NodeRef>()
{
public NodeRef execute() throws Throwable
{
// Tidy up failed runs
if (personService.personExists(oldUsername))
{
personService.deletePerson(oldUsername);
}
if (personService.personExists(newUsername))
{
personService.deletePerson(newUsername);
}
// Generate a person node
Map<QName, Serializable> properties = createDefaultProperties(oldUsername, "firstName", "lastName", "email@orgId", "orgId", null);
NodeRef person = personService.createPerson(properties);
// Check the person exists
assertEquals(oldUsername, nodeService.getProperty(person, ContentModel.PROP_USERNAME));
assertEquals(person, personService.getPerson(oldUsername));
assertFalse("new user should not exist yet", personService.personExists(newUsername));
return person;
}
}, false, true);
// Run the RenameUser cmd line tool
// - override exit so we don't and assert normal exit
// - Don't ask for a password as we may not know it in a test
// - call start rather than main to get correct instance
RenameUser renameUser = new RenameUser()
{
@Override
protected void exit(int status)
{
assertEquals("Tool exit status should be normal", 0, status);
}
};
renameUser.setLogin(false);
renameUser.start(new String[] {"-user", username, oldUsername, newUsername});
// Check person has been renamed and the delete it.
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
String newUserName = (String) nodeService.getProperty(person, ContentModel.PROP_USERNAME);
assertEquals(newUsername, newUserName);
// Check the person exists
assertEquals(newUsername, nodeService.getProperty(person, ContentModel.PROP_USERNAME));
assertEquals(person, personService.getPerson(newUsername));
assertFalse("old user should no longer exist", personService.personExists(oldUsername));
// Get rid of the test person
personService.deletePerson(newUsername);
return null;
}
}, false, true);
}
}

View File

@@ -0,0 +1,561 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* 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/>.
*/
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;
}
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* 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/>.
*/
package org.alfresco.tools;
import static org.junit.Assert.assertEquals;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.Iterator;
import org.alfresco.tools.RenameUser.User;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Unit test for RenameUser. {@link PersonTest} contains integration tests.
*
* @author Alan Davis
*/
public class RenameUserTest
{
private String[] args;
private File file;
private RenameUser renameUser = new RenameUser();
@Before
public void setUp() throws Exception
{
args = new String[6];
args[0] = "-user";
args[1] = "admin";
args[2] = "-pwd";
args[3] = "admin";
args[4] = "oldUsername";
args[5] = "newUsername";
}
@After
public void tearDown()// throws Exception
{
if (file != null && file.exists())
{
file.delete();
}
}
private void createFile(String content) throws Exception
{
file = File.createTempFile("RenameUserTest", ".txt");
args[4] = "-file";
args[5] = file.getPath();
BufferedWriter out = new BufferedWriter(new FileWriter(file));
out.write(content);
out.close();
}
private void processArgsAndValidate()
{
renameUser.processArgs(args);
renameUser.context.validate();
}
// Check that the expected (supplied) usernames are in the context
private void assertUsers(String... usernames)
{
int length = usernames.length/2;
assertEquals("Must have an even number of usernames passed to assertUsers", usernames.length, length*2);
assertEquals(length, renameUser.context.userCount());
Iterator<User> iterator = renameUser.context.iterator();
for (int i=0; i<length; i++)
{
User user = iterator.next();
assertEquals(usernames[i*2], user.getOldUsername());
assertEquals(usernames[i*2+1], user.getNewUsername());
}
}
@Test
public void testLoginUsernameAndPassword() throws Exception
{
// Reset the password to be sure we are picking up the correct value.
args[3] = "password";
renameUser.processArgs(args);
assertEquals("admin", renameUser.context.getUsername());
assertEquals("password", renameUser.context.getPassword());
}
@Test
public void testCmdLineUsernames() throws Exception
{
renameUser.processArgs(args);
assertUsers("oldUsername", "newUsername");
}
@Test
public void testFileUsernames() throws Exception
{
createFile("oldUsername1,newUsername1\n");
processArgsAndValidate();
assertUsers("oldUsername1", "newUsername1");
}
@Test
public void testFileUsernamesWithSpaces() throws Exception
{
createFile(" oldUsername1 , newUsername1 \n");
processArgsAndValidate();
assertUsers("oldUsername1", "newUsername1");
}
@Test
public void testFileMultipleUsernames() throws Exception
{
createFile("oldUsername1,newUsername1\n" +
"oldUsername2,newUsername2\n");
processArgsAndValidate();
assertUsers("oldUsername1", "newUsername1",
"oldUsername2", "newUsername2");
}
@Test
public void testFileNoNewlineAtEndOfFile() throws Exception
{
createFile("oldUsername1,newUsername1");
processArgsAndValidate();
assertUsers("oldUsername1", "newUsername1");
}
@Test
public void testEmptyLines() throws Exception
{
createFile("\n\noldUsername1,newUsername1\n\n");
processArgsAndValidate();
assertUsers("oldUsername1", "newUsername1");
}
@Test
public void testComments() throws Exception
{
createFile("#A header comment\noldUsername1,newUsername1 #end of line comment\n\n");
processArgsAndValidate();
assertUsers("oldUsername1", "newUsername1");
}
@Test(expected=ToolArgumentException.class)
public void testBadFilename() throws Exception
{
createFile("oldUsername1,newUsername1\n");
args[5] = "rubbish.txt";
processArgsAndValidate();
}
@Test(expected=ToolArgumentException.class)
public void testFileNoUsernames() throws Exception
{
createFile("#A comment\n");
processArgsAndValidate();
}
@Test(expected=ToolArgumentException.class)
public void testTooManyUsernamesOnALine() throws Exception
{
createFile("\nname1,name2,name3\n");
processArgsAndValidate();
}
@Test(expected=ToolArgumentException.class)
public void testDuplicateNewUsername() throws Exception
{
createFile("name1,name2\nname3,name1\n");
processArgsAndValidate();
}
@Test(expected=ToolArgumentException.class)
public void testDuplicateOldUsername() throws Exception
{
createFile("name1,name2\nname2,name3\n");
processArgsAndValidate();
}
@Test(expected=ToolArgumentException.class)
public void testSameUsernameCmdLine() throws Exception
{
args[5] = "oldUsername";
processArgsAndValidate();
}
@Test(expected=ToolArgumentException.class)
public void testSameUsernameFile() throws Exception
{
createFile("name1,name1");
processArgsAndValidate();
}
}

View File

@@ -220,9 +220,15 @@ public abstract class Tool
// Perform Tool behaviour
logInfo(getToolName());
initialiseRepository();
if (toolContext.isLogin())
{
login();
}
long loginTime = System.nanoTime();
if (toolContext.isLogin())
{
logInfo("Time to login "+((loginTime - startTime)/1000000000f)+" seconds");
}
status = execute();
long executeTime = System.nanoTime();
logInfo("Time to execute "+((executeTime - loginTime)/1000000000f)+" seconds");