/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.eperson;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.codec.DecoderException;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.*;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.core.Utils;
import org.dspace.event.Event;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;
/**
* Class representing an e-person.
*
* @author David Stuve
* @version $Revision$
*/
public class EPerson extends DSpaceObject
{
/** The e-mail field (for sorting) */
public static final int EMAIL = 1;
/** The last name (for sorting) */
public static final int LASTNAME = 2;
/** The e-mail field (for sorting) */
public static final int ID = 3;
/** The netid field (for sorting) */
public static final int NETID = 4;
/** The e-mail field (for sorting) */
public static final int LANGUAGE = 5;
/** log4j logger */
private static final Logger log = Logger.getLogger(EPerson.class);
/** The row in the table representing this eperson */
private final TableRow myRow;
/** Flag set when data is modified, for events */
private boolean modified;
/**
* Construct an EPerson
*
* @param context
* the context this object exists in
* @param row
* the corresponding row in the table
*/
EPerson(Context context, TableRow row) throws SQLException {
super(context);
myRow = row;
// Cache ourselves
context.cache(this, row.getIntColumn("eperson_id"));
modified = false;
clearDetails();
}
/**
* Return true if this object equals obj, false otherwise.
*
* @param obj
* @return true if ResourcePolicy objects are equal
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final EPerson other = (EPerson) obj;
if (this.getID() != other.getID())
{
return false;
}
if (!this.getEmail().equals(other.getEmail()))
{
return false;
}
if (!this.getFullName().equals(other.getFullName()))
{
return false;
}
return true;
}
/**
* Return a hash code for this object.
*
* @return int hash of object
*/
@Override
public int hashCode()
{
int hash = 5;
hash = 89 * hash + this.getID();
hash = 89 * hash + (this.getEmail() != null? this.getEmail().hashCode():0);
hash = 89 * hash + (this.getFullName() != null? this.getFullName().hashCode():0);
return hash;
}
/**
* Get an EPerson from the database.
*
* @param context
* DSpace context object
* @param id
* ID of the EPerson
*
* @return the EPerson format, or null if the ID is invalid.
*/
public static EPerson find(Context context, int id) throws SQLException
{
// First check the cache
EPerson fromCache = (EPerson) context.fromCache(EPerson.class, id);
if (fromCache != null)
{
return fromCache;
}
TableRow row = DatabaseManager.find(context, "eperson", id);
if (row == null)
{
return null;
}
else
{
return new EPerson(context, row);
}
}
/**
* Find the eperson by their email address.
*
* @return EPerson, or {@code null} if none such exists.
*/
public static EPerson findByEmail(Context context, String email)
throws SQLException, AuthorizeException
{
if (email == null)
{
return null;
}
// All email addresses are stored as lowercase, so ensure that the email address is lowercased for the lookup
TableRow row = DatabaseManager.findByUnique(context, "eperson",
"email", email.toLowerCase());
if (row == null)
{
return null;
}
else
{
// First check the cache
EPerson fromCache = (EPerson) context.fromCache(EPerson.class, row
.getIntColumn("eperson_id"));
if (fromCache != null)
{
return fromCache;
}
else
{
return new EPerson(context, row);
}
}
}
/**
* Find the eperson by their netid.
*
* @param context
* DSpace context
* @param netid
* Network ID
*
* @return corresponding EPerson, or <code>null</code>
*/
public static EPerson findByNetid(Context context, String netid)
throws SQLException
{
if (netid == null)
{
return null;
}
TableRow row = DatabaseManager.findByUnique(context, "eperson", "netid", netid);
if (row == null)
{
return null;
}
else
{
// First check the cache
EPerson fromCache = (EPerson) context.fromCache(EPerson.class, row
.getIntColumn("eperson_id"));
if (fromCache != null)
{
return fromCache;
}
else
{
return new EPerson(context, row);
}
}
}
/**
* Find the epeople that match the search query across firstname, lastname or email.
*
* @param context
* DSpace context
* @param query
* The search string
*
* @return array of EPerson objects
*/
public static EPerson[] search(Context context, String query)
throws SQLException
{
return search(context, query, -1, -1);
}
/**
* Find the epeople that match the search query across firstname, lastname or email.
* This method also allows offsets and limits for pagination purposes.
*
* @param context
* DSpace context
* @param query
* The search string
* @param offset
* Inclusive offset
* @param limit
* Maximum number of matches returned
*
* @return array of EPerson objects
*/
public static EPerson[] search(Context context, String query, int offset, int limit)
throws SQLException
{
String params = "%"+query.toLowerCase()+"%";
StringBuffer queryBuf = new StringBuffer();
queryBuf.append("select e.* from eperson e " +
" LEFT JOIN metadatavalue fn on (resource_id=e.eperson_id AND fn.resource_type_id=? and fn.metadata_field_id=?) " +
" LEFT JOIN metadatavalue ln on (ln.resource_id=e.eperson_id AND ln.resource_type_id=? and ln.metadata_field_id=?) " +
" WHERE e.eperson_id = ? OR " +
"LOWER(fn.text_value) LIKE LOWER(?) OR LOWER(ln.text_value) LIKE LOWER(?) OR LOWER(email) LIKE LOWER(?) ORDER BY ");
if(DatabaseManager.isOracle()) {
queryBuf.append(" dbms_lob.substr(ln.text_value), dbms_lob.substr(fn.text_value) ASC");
}else{
queryBuf.append(" ln.text_value, fn.text_value ASC");
}
// Add offset and limit restrictions - Oracle requires special code
if (DatabaseManager.isOracle())
{
// First prepare the query to generate row numbers
if (limit > 0 || offset > 0)
{
queryBuf.insert(0, "SELECT /*+ FIRST_ROWS(n) */ rec.*, ROWNUM rnum FROM (");
queryBuf.append(") ");
}
// Restrict the number of rows returned based on the limit
if (limit > 0)
{
queryBuf.append("rec WHERE rownum<=? ");
// If we also have an offset, then convert the limit into the maximum row number
if (offset > 0)
{
limit += offset;
}
}
// Return only the records after the specified offset (row number)
if (offset > 0)
{
queryBuf.insert(0, "SELECT * FROM (");
queryBuf.append(") WHERE rnum>?");
}
}
else
{
if (limit > 0)
{
queryBuf.append(" LIMIT ? ");
}
if (offset > 0)
{
queryBuf.append(" OFFSET ? ");
}
}
String dbquery = queryBuf.toString();
// When checking against the eperson-id, make sure the query can be made into a number
Integer int_param;
try {
int_param = Integer.valueOf(query);
}
catch (NumberFormatException e) {
int_param = Integer.valueOf(-1);
}
Integer f = MetadataField.findByElement(context, MetadataSchema.find(context, "eperson").getSchemaID(), "firstname", null).getFieldID();
Integer l = MetadataField.findByElement(context, MetadataSchema.find(context, "eperson").getSchemaID(), "lastname", null).getFieldID();
// Create the parameter array, including limit and offset if part of the query
Object[] paramArr = new Object[] {Constants.EPERSON,f, Constants.EPERSON,l, int_param,params,params,params};
if (limit > 0 && offset > 0)
{
paramArr = new Object[]{Constants.EPERSON,f, Constants.EPERSON,l, int_param,params,params,params, limit, offset};
}
else if (limit > 0)
{
paramArr = new Object[]{Constants.EPERSON,f, Constants.EPERSON,l, int_param,params,params,params, limit};
}
else if (offset > 0)
{
paramArr = new Object[]{Constants.EPERSON,f, Constants.EPERSON,l, int_param,params,params,params, offset};
}
// Get all the epeople that match the query
TableRowIterator rows = DatabaseManager.query(context,
dbquery, paramArr);
try
{
List<TableRow> epeopleRows = rows.toList();
EPerson[] epeople = new EPerson[epeopleRows.size()];
for (int i = 0; i < epeopleRows.size(); i++)
{
TableRow row = (TableRow) epeopleRows.get(i);
// First check the cache
EPerson fromCache = (EPerson) context.fromCache(EPerson.class, row
.getIntColumn("eperson_id"));
if (fromCache != null)
{
epeople[i] = fromCache;
}
else
{
epeople[i] = new EPerson(context, row);
}
}
return epeople;
}
finally
{
if (rows != null)
{
rows.close();
}
}
}
/**
* Returns the total number of epeople returned by a specific query, without the overhead
* of creating the EPerson objects to store the results.
*
* @param context
* DSpace context
* @param query
* The search string
*
* @return the number of epeople matching the query
*/
public static int searchResultCount(Context context, String query)
throws SQLException
{
String dbquery = "%"+query.toLowerCase()+"%";
Long count;
// When checking against the eperson-id, make sure the query can be made into a number
Integer int_param;
try {
int_param = Integer.valueOf(query);
}
catch (NumberFormatException e) {
int_param = Integer.valueOf(-1);
}
// Get all the epeople that match the query
TableRow row = DatabaseManager.querySingle(context,
"SELECT count(*) as epcount FROM eperson " +
"WHERE eperson_id = ? OR " +
"LOWER((select text_value from metadatavalue where resource_id=? and resource_type_id=? and metadata_field_id=?)) LIKE LOWER(?) " +
"OR LOWER((select text_value from metadatavalue where resource_id=? and resource_type_id=? and metadata_field_id=?)) LIKE LOWER(?) " +
"OR LOWER(eperson.email) LIKE LOWER(?)",
new Object[] {
int_param,
int_param,
Constants.EPERSON,
MetadataField.findByElement(context, MetadataSchema.find(context, "eperson").getSchemaID(), "firstname", null).getFieldID(),
dbquery,
int_param,
Constants.EPERSON,
MetadataField.findByElement(context, MetadataSchema.find(context, "eperson").getSchemaID(), "lastname", null).getFieldID(),
dbquery,
dbquery
});
// use getIntColumn for Oracle count data
if (DatabaseManager.isOracle())
{
count = Long.valueOf(row.getIntColumn("epcount"));
}
else //getLongColumn works for postgres
{
count = Long.valueOf(row.getLongColumn("epcount"));
}
return count.intValue();
}
/**
* Find all the epeople that match a particular query
* <ul>
* <li><code>ID</code></li>
* <li><code>LASTNAME</code></li>
* <li><code>EMAIL</code></li>
* <li><code>NETID</code></li>
* </ul>
*
* @return array of EPerson objects
*/
public static EPerson[] findAll(Context context, int sortField)
throws SQLException
{
String s, t = "", theQuery = "";
switch (sortField)
{
case ID:
s = "e.eperson_id";
break;
case EMAIL:
s = "e.email";
break;
case LANGUAGE:
s = "m_text_value";
t = "language";
break;
case NETID:
s = "e.netid";
break;
default:
s = "m_text_value";
t = "lastname";
}
// NOTE: The use of 's' in the order by clause can not cause an SQL
// injection because the string is derived from constant values above.
TableRowIterator rows = DatabaseManager.query(context, "SELECT * FROM eperson e ORDER BY ?",s);
if(!t.equals("")) {
rows = DatabaseManager.query(context,
"SELECT * FROM eperson e " +
"LEFT JOIN metadatavalue m on (m.resource_id = e.eperson_id and m.resource_type_id = ? and m.metadata_field_id = ?) " +
"ORDER BY ?",
Constants.EPERSON,
MetadataField.findByElement(context, MetadataSchema.find(context, "eperson").getSchemaID(), t, null).getFieldID(),
s
);
}
try
{
List<TableRow> epeopleRows = rows.toList();
EPerson[] epeople = new EPerson[epeopleRows.size()];
for (int i = 0; i < epeopleRows.size(); i++)
{
TableRow row = (TableRow) epeopleRows.get(i);
// First check the cache
EPerson fromCache = (EPerson) context.fromCache(EPerson.class, row
.getIntColumn("eperson_id"));
if (fromCache != null)
{
epeople[i] = fromCache;
}
else
{
epeople[i] = new EPerson(context, row);
}
}
return epeople;
}
finally
{
if (rows != null)
{
rows.close();
}
}
}
/**
* Create a new eperson
*
* @param context
* DSpace context object
*/
public static EPerson create(Context context) throws SQLException,
AuthorizeException
{
// authorized?
if (!AuthorizeManager.isAdmin(context))
{
throw new AuthorizeException(
"You must be an admin to create an EPerson");
}
// Create a table row
TableRow row = DatabaseManager.create(context, "eperson");
EPerson e = new EPerson(context, row);
log.info(LogManager.getHeader(context, "create_eperson", "eperson_id="
+ e.getID()));
context.addEvent(new Event(Event.CREATE, Constants.EPERSON, e.getID(),
null, e.getIdentifiers(context)));
return e;
}
/**
* Delete an eperson
*
*/
public void delete() throws SQLException, AuthorizeException,
EPersonDeletionException
{
// authorized?
if (!AuthorizeManager.isAdmin(ourContext))
{
throw new AuthorizeException(
"You must be an admin to delete an EPerson");
}
// check for presence of eperson in tables that
// have constraints on eperson_id
List<String> constraintList = getDeleteConstraints();
// if eperson exists in tables that have constraints
// on eperson, throw an exception
if (constraintList.size() > 0)
{
throw new EPersonDeletionException(constraintList);
}
// Delete the Dublin Core
removeMetadataFromDatabase();
ourContext.addEvent(new Event(Event.DELETE, Constants.EPERSON, getID(), getEmail(), getIdentifiers(ourContext)));
// Remove from cache
ourContext.removeCached(this, getID());
// XXX FIXME: This sidesteps the object model code so it won't
// generate REMOVE events on the affected Groups.
// Remove any group memberships first
DatabaseManager.updateQuery(ourContext,
"DELETE FROM EPersonGroup2EPerson WHERE eperson_id= ? ",
getID());
// Remove any subscriptions
DatabaseManager.updateQuery(ourContext,
"DELETE FROM subscription WHERE eperson_id= ? ",
getID());
// Remove ourself
DatabaseManager.delete(ourContext, myRow);
log.info(LogManager.getHeader(ourContext, "delete_eperson",
"eperson_id=" + getID()));
}
/**
* Get the e-person's internal identifier
*
* @return the internal identifier
*/
public int getID()
{
return myRow.getIntColumn("eperson_id");
}
/**
* Get the e-person's language
*
* @return language code (or null if the column is an SQL NULL)
*/
public String getLanguage()
{
return getMetadataFirstValue("eperson", "language", null, Item.ANY);
}
/**
* Set the EPerson's language. Value is expected to be a Unix/POSIX
* Locale specification of the form {language} or {language}_{territory},
* e.g. "en", "en_US", "pt_BR" (the latter is Brazilian Portugese).
*
* @param language
* language code
*/
public void setLanguage(String language) {
setMetadataSingleValue("eperson", "language", null, null, language);
}
/**
* Get the e-person's handle
*
* @return current implementation always returns null
*/
public String getHandle()
{
// No Handles for e-people
return null;
}
/**
* Get the e-person's email address
*
* @return their email address (or null if the column is an SQL NULL)
*/
public String getEmail()
{
return myRow.getStringColumn("email");
}
/**
* Set the EPerson's email
*
* @param s
* the new email
*/
public void setEmail(String s)
{
if (s != null)
{
s = s.toLowerCase();
}
myRow.setColumn("email", s);
modified = true;
}
/**
* Get the e-person's netid
*
* @return their netid (DB constraints ensure it's never NULL)
*/
public String getNetid()
{
return myRow.getStringColumn("netid");
}
/**
* Set the EPerson's netid
*
* @param s
* the new netid
*/
public void setNetid(String s) {
myRow.setColumn("netid", s);
modified = true;
}
/**
* Get the e-person's full name, combining first and last name in a
* displayable string.
*
* @return their full name (first + last name; if both are NULL, returns email)
*/
public String getFullName()
{
String f = getFirstName();
String l= getLastName();
if ((l == null) && (f == null))
{
return getEmail();
}
else if (f == null)
{
return l;
}
else
{
return (f + " " + l);
}
}
/**
* Get the eperson's first name.
*
* @return their first name (or null if the column is an SQL NULL)
*/
public String getFirstName()
{
return getMetadataFirstValue("eperson", "firstname", null, Item.ANY);
}
/**
* Set the eperson's first name
*
* @param firstname
* the person's first name
*/
public void setFirstName(String firstname) {
setMetadataSingleValue("eperson", "firstname", null, null, firstname);
modified = true;
}
/**
* Get the eperson's last name.
*
* @return their last name (or null if the column is an SQL NULL)
*/
public String getLastName()
{
return getMetadataFirstValue("eperson", "lastname", null, Item.ANY);
}
/**
* Set the eperson's last name
*
* @param lastname
* the person's last name
*/
public void setLastName(String lastname) {
setMetadataSingleValue("eperson", "lastname", null, null, lastname);
modified = true;
}
/**
* Indicate whether the user can log in
*
* @param login
* boolean yes/no
*/
public void setCanLogIn(boolean login)
{
myRow.setColumn("can_log_in", login);
modified = true;
}
/**
* Can the user log in?
*
* @return boolean, yes/no
*/
public boolean canLogIn()
{
return myRow.getBooleanColumn("can_log_in");
}
/**
* Set require cert yes/no
*
* @param isrequired
* boolean yes/no
*/
public void setRequireCertificate(boolean isrequired)
{
myRow.setColumn("require_certificate", isrequired);
modified = true;
}
/**
* Get require certificate or not
*
* @return boolean, yes/no (or false if the column is an SQL NULL)
*/
public boolean getRequireCertificate()
{
return myRow.getBooleanColumn("require_certificate");
}
/**
* Indicate whether the user self-registered
*
* @param sr
* boolean yes/no
*/
public void setSelfRegistered(boolean sr)
{
myRow.setColumn("self_registered", sr);
modified = true;
}
/**
* Is the user self-registered?
*
* @return boolean, yes/no (or false if the column is an SQL NULL)
*/
public boolean getSelfRegistered()
{
return myRow.getBooleanColumn("self_registered");
}
/**
* Get the value of a metadata field
*
* @param field
* the name of the metadata field to get
*
* @return the value of the metadata field (or null if the column is an SQL NULL)
*
* @exception IllegalArgumentException
* if the requested metadata field doesn't exist
*/
@Deprecated
public String getMetadata(String field)
{
String[] MDValue = getMDValueByLegacyField(field);
return getMetadataFirstValue(MDValue[0], MDValue[1], MDValue[2], Item.ANY);
}
/**
* Set a metadata value
*
* @param field
* the name of the metadata field to set
* @param value
* value to set the field to
*
* @exception IllegalArgumentException
* if the requested metadata field doesn't exist
*/
@Deprecated
public void setMetadata(String field, String value)
{
String[] MDValue = getMDValueByLegacyField(field);
setMetadataSingleValue(MDValue[0], MDValue[1], MDValue[2], null, value);
}
/**
* Set the EPerson's password.
*
* @param s
* the new password.
*/
public void setPassword(String s)
{
PasswordHash hash = new PasswordHash(s);
myRow.setColumn("password", Utils.toHex(hash.getHash()));
myRow.setColumn("salt", Utils.toHex(hash.getSalt()));
myRow.setColumn("digest_algorithm", hash.getAlgorithm());
modified = true;
}
/**
* Set the EPerson's password hash.
*
* @param password
* hashed password, or null to set row data to NULL.
*/
public void setPasswordHash(PasswordHash password)
{
if (null == password)
{
myRow.setColumnNull("digest_algorithm");
myRow.setColumnNull("salt");
myRow.setColumnNull("password");
}
else
{
myRow.setColumn("digest_algorithm", password.getAlgorithm());
myRow.setColumn("salt", password.getSaltString());
myRow.setColumn("password", password.getHashString());
}
modified = true;
}
/**
* Return the EPerson's password hash.
*
* @return hash of the password, or null on failure (such as no password).
*/
public PasswordHash getPasswordHash()
{
PasswordHash hash = null;
try {
hash = new PasswordHash(myRow.getStringColumn("digest_algorithm"),
myRow.getStringColumn("salt"),
myRow.getStringColumn("password"));
} catch (DecoderException ex) {
log.error("Problem decoding stored salt or hash: " + ex.getMessage());
}
return hash;
}
/**
* Check EPerson's password. Side effect: original unsalted MD5 hashes are
* converted using the current algorithm.
*
* @param attempt
* the password attempt
* @return boolean successful/unsuccessful
*/
public boolean checkPassword(String attempt)
{
PasswordHash myHash;
try
{
myHash = new PasswordHash(
myRow.getStringColumn("digest_algorithm"),
myRow.getStringColumn("salt"),
myRow.getStringColumn("password"));
} catch (DecoderException ex)
{
log.error(ex.getMessage());
return false;
}
boolean answer = myHash.matches(attempt);
// If using the old unsalted hash, and this password is correct, update to a new hash
if (answer && (null == myRow.getStringColumn("digest_algorithm")))
{
log.info("Upgrading password hash for EPerson " + getID());
setPassword(attempt);
try {
ourContext.turnOffAuthorisationSystem();
update();
} catch (SQLException ex) {
log.error("Could not update password hash", ex);
} catch (AuthorizeException ex) {
log.error("Could not update password hash", ex);
} finally {
ourContext.restoreAuthSystemState();
}
}
return answer;
}
/**
* Stamp the EPerson's last-active date.
*
* @param when latest activity timestamp, or null to clear.
*/
public void setLastActive(Date when)
{
myRow.setColumn("last_active", when);
}
/**
* Get the EPerson's last-active stamp.
*
* @return date when last logged on, or null.
*/
public Date getLastActive()
{
return myRow.getDateColumn("last_active");
}
/**
* Update the EPerson
*/
public void update() throws SQLException, AuthorizeException
{
// Check authorisation - if you're not the eperson
// see if the authorization system says you can
if (!ourContext.ignoreAuthorization()
&& ((ourContext.getCurrentUser() == null) || (getID() != ourContext
.getCurrentUser().getID())))
{
AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE);
}
DatabaseManager.update(ourContext, myRow);
log.info(LogManager.getHeader(ourContext, "update_eperson",
"eperson_id=" + getID()));
if (modified)
{
ourContext.addEvent(new Event(Event.MODIFY, Constants.EPERSON,
getID(), null, getIdentifiers(ourContext)));
modified = false;
}
if (modifiedMetadata)
{
updateMetadata();
clearDetails();
}
}
/**
* return type found in Constants
*/
public int getType()
{
return Constants.EPERSON;
}
/**
* Check for presence of EPerson in tables that have constraints on
* EPersons. Called by delete() to determine whether the eperson can
* actually be deleted.
*
* An EPerson cannot be deleted if it exists in the item, workflowitem, or
* tasklistitem tables.
*
* @return List of tables that contain a reference to the eperson.
*/
public List<String> getDeleteConstraints() throws SQLException
{
List<String> tableList = new ArrayList<String>();
// check for eperson in item table
TableRowIterator tri = DatabaseManager.query(ourContext,
"SELECT * from item where submitter_id= ? ",
getID());
try
{
if (tri.hasNext())
{
tableList.add("item");
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
{
tri.close();
}
}
if(ConfigurationManager.getProperty("workflow","workflow.framework").equals("xmlworkflow")){
getXMLWorkflowConstraints(tableList);
}else{
getOriginalWorkflowConstraints(tableList);
}
// the list of tables can be used to construct an error message
// explaining to the user why the eperson cannot be deleted.
return tableList;
}
private void getXMLWorkflowConstraints(List<String> tableList) throws SQLException {
TableRowIterator tri;
// check for eperson in claimtask table
tri = DatabaseManager.queryTable(ourContext, "cwf_claimtask",
"SELECT * from cwf_claimtask where owner_id= ? ",
getID());
try
{
if (tri.hasNext())
{
tableList.add("cwf_claimtask");
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
{
tri.close();
}
}
// check for eperson in pooltask table
tri = DatabaseManager.queryTable(ourContext, "cwf_pooltask",
"SELECT * from cwf_pooltask where eperson_id= ? ",
getID());
try
{
if (tri.hasNext())
{
tableList.add("cwf_pooltask");
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
{
tri.close();
}
}
// check for eperson in workflowitemrole table
tri = DatabaseManager.queryTable(ourContext, "cwf_workflowitemrole",
"SELECT * from cwf_workflowitemrole where eperson_id= ? ",
getID());
try
{
if (tri.hasNext())
{
tableList.add("cwf_workflowitemrole");
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
{
tri.close();
}
}
}
private void getOriginalWorkflowConstraints(List<String> tableList) throws SQLException {
TableRowIterator tri;
// check for eperson in workflowitem table
tri = DatabaseManager.query(ourContext,
"SELECT * from workflowitem where owner= ? ",
getID());
try
{
if (tri.hasNext())
{
tableList.add("workflowitem");
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
{
tri.close();
}
}
// check for eperson in tasklistitem table
tri = DatabaseManager.query(ourContext,
"SELECT * from tasklistitem where eperson_id= ? ",
getID());
try
{
if (tri.hasNext())
{
tableList.add("tasklistitem");
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
{
tri.close();
}
}
}
@Override
public String getName()
{
return getEmail();
}
@Override
public void updateLastModified()
{
}
/*
* Commandline tool for manipulating EPersons.
*/
private static final Option VERB_ADD = new Option("a", "add", false, "create a new EPerson");
private static final Option VERB_DELETE = new Option("d", "delete", false, "delete an existing EPerson");
private static final Option VERB_LIST = new Option("L", "list", false, "list EPersons");
private static final Option VERB_MODIFY = new Option("M", "modify", false, "modify an EPerson");
private static final Option OPT_GIVENNAME = new Option("g", "givenname", true, "the person's actual first or personal name");
private static final Option OPT_SURNAME = new Option("s", "surname", true, "the person's actual last or family name");
private static final Option OPT_PHONE = new Option("t", "telephone", true, "telephone number, empty for none");
private static final Option OPT_LANGUAGE = new Option("l", "language", true, "the person's preferred language");
private static final Option OPT_REQUIRE_CERTIFICATE = new Option("c", "requireCertificate", true, "if 'true', an X.509 certificate will be required for login");
private static final Option OPT_CAN_LOGIN = new Option("C", "canLogIn", true, "'true' if the user can log in");
private static final Option OPT_EMAIL = new Option("m", "email", true, "the user's email address, empty for none");
private static final Option OPT_NETID = new Option("n", "netid", true, "network ID associated with the person, empty for none");
private static final Option OPT_NEW_EMAIL = new Option("i", "newEmail", true, "new email address");
private static final Option OPT_NEW_NETID = new Option("I", "newNetid", true, "new network ID");
/**
* Tool for manipulating user accounts.
*/
public static void main(String argv[])
throws ParseException, SQLException, AuthorizeException {
final OptionGroup VERBS = new OptionGroup();
VERBS.addOption(VERB_ADD);
VERBS.addOption(VERB_DELETE);
VERBS.addOption(VERB_LIST);
VERBS.addOption(VERB_MODIFY);
final Options globalOptions = new Options();
globalOptions.addOptionGroup(VERBS);
globalOptions.addOption("h", "help", false, "explain options");
GnuParser parser = new GnuParser();
CommandLine command = parser.parse(globalOptions, argv, true);
Context context = new Context();
// Disable authorization since this only runs from the local commandline.
context.turnOffAuthorisationSystem();
int status = 0;
if (command.hasOption(VERB_ADD.getOpt()))
{
status = cmdAdd(context, argv);
}
else if (command.hasOption(VERB_DELETE.getOpt()))
{
status = cmdDelete(context, argv);
}
else if (command.hasOption(VERB_MODIFY.getOpt()))
{
status = cmdModify(context, argv);
}
else if (command.hasOption(VERB_LIST.getOpt()))
{
status = cmdList(context, argv);
}
else if (command.hasOption('h'))
{
new HelpFormatter().printHelp("user [options]", globalOptions);
}
else
{
System.err.println("Unknown operation.");
new HelpFormatter().printHelp("user [options]", globalOptions);
context.abort();
status = 1;
throw new IllegalArgumentException();
}
if (context.isValid())
{
try {
context.complete();
} catch (SQLException ex) {
System.err.println(ex.getMessage());
}
}
}
/** Command to create an EPerson. */
private static int cmdAdd(Context context, String[] argv) throws AuthorizeException {
Options options = new Options();
options.addOption(VERB_ADD);
final OptionGroup identityOptions = new OptionGroup();
identityOptions.addOption(OPT_EMAIL);
identityOptions.addOption(OPT_NETID);
options.addOptionGroup(identityOptions);
options.addOption(OPT_GIVENNAME);
options.addOption(OPT_SURNAME);
options.addOption(OPT_PHONE);
options.addOption(OPT_LANGUAGE);
options.addOption(OPT_REQUIRE_CERTIFICATE);
Option option = new Option("p", "password", true, "password to match the EPerson name");
options.addOption(option);
options.addOption("h", "help", false, "explain --add options");
// Rescan the command for more details.
GnuParser parser = new GnuParser();
CommandLine command;
try {
command = parser.parse(options, argv);
} catch (ParseException e) {
System.err.println(e.getMessage());
return 1;
}
if (command.hasOption('h'))
{
new HelpFormatter().printHelp("user --add [options]", options);
return 0;
}
// Check that we got sufficient credentials to define a user.
if ((!command.hasOption(OPT_EMAIL.getOpt())) && (!command.hasOption(OPT_NETID.getOpt())))
{
System.err.println("You must provide an email address or a netid to identify the new user.");
return 1;
}
if (!command.hasOption('p'))
{
System.err.println("You must provide a password for the new user.");
return 1;
}
// Create!
EPerson eperson = null;
try {
eperson = create(context);
} catch (SQLException ex) {
context.abort();
System.err.println(ex.getMessage());
return 1;
} catch (AuthorizeException ex) { /* XXX SNH */ }
eperson.setCanLogIn(true);
eperson.setSelfRegistered(false);
eperson.setEmail(command.getOptionValue(OPT_EMAIL.getOpt()));
eperson.setFirstName(command.getOptionValue(OPT_GIVENNAME.getOpt()));
eperson.setLastName(command.getOptionValue(OPT_SURNAME.getOpt()));
eperson.setLanguage(command.getOptionValue(OPT_LANGUAGE.getOpt(),
Locale.getDefault().getLanguage()));
eperson.setMetadata("phone", command.getOptionValue(OPT_PHONE.getOpt()));
eperson.setNetid(command.getOptionValue(OPT_NETID.getOpt()));
eperson.setPassword(command.getOptionValue('p'));
if (command.hasOption(OPT_REQUIRE_CERTIFICATE.getOpt()))
{
eperson.setRequireCertificate(Boolean.valueOf(command.getOptionValue(
OPT_REQUIRE_CERTIFICATE.getOpt())));
}
else
{
eperson.setRequireCertificate(false);
}
try {
eperson.update();
context.commit();
System.out.printf("Created EPerson %d\n", eperson.getID());
} catch (SQLException ex) {
context.abort();
System.err.println(ex.getMessage());
return 1;
} catch (AuthorizeException ex) { /* XXX SNH */ }
return 0;
}
/** Command to delete an EPerson. */
private static int cmdDelete(Context context, String[] argv)
{
Options options = new Options();
options.addOption(VERB_DELETE);
final OptionGroup identityOptions = new OptionGroup();
identityOptions.addOption(OPT_EMAIL);
identityOptions.addOption(OPT_NETID);
options.addOptionGroup(identityOptions);
options.addOption("h", "help", false, "explain --delete options");
GnuParser parser = new GnuParser();
CommandLine command;
try {
command = parser.parse(options, argv);
} catch (ParseException e) {
System.err.println(e.getMessage());
return 1;
}
if (command.hasOption('h'))
{
new HelpFormatter().printHelp("user --delete [options]", options);
return 0;
}
// Delete!
EPerson eperson = null;
try {
if (command.hasOption(OPT_NETID.getOpt()))
{
eperson = findByNetid(context, command.getOptionValue(OPT_NETID.getOpt()));
}
else if (command.hasOption(OPT_EMAIL.getOpt()))
{
eperson = findByEmail(context, command.getOptionValue(OPT_EMAIL.getOpt()));
}
else
{
System.err.println("You must specify the user's email address or netid.");
return 1;
}
} catch (SQLException e) {
System.err.append(e.getMessage());
return 1;
} catch (AuthorizeException e) { /* XXX SNH */ }
if (null == eperson)
{
System.err.println("No such EPerson");
return 1;
}
try {
eperson.delete();
context.commit();
System.out.printf("Deleted EPerson %d\n", eperson.getID());
} catch (SQLException ex) {
System.err.println(ex.getMessage());
return 1;
} catch (AuthorizeException ex) {
System.err.println(ex.getMessage());
return 1;
} catch (EPersonDeletionException ex) {
System.err.println(ex.getMessage());
return 1;
}
return 0;
}
/** Command to modify an EPerson. */
private static int cmdModify(Context context, String[] argv) throws AuthorizeException {
Options options = new Options();
options.addOption(VERB_MODIFY);
final OptionGroup identityOptions = new OptionGroup();
identityOptions.addOption(OPT_EMAIL);
identityOptions.addOption(OPT_NETID);
options.addOptionGroup(identityOptions);
options.addOption(OPT_GIVENNAME);
options.addOption(OPT_SURNAME);
options.addOption(OPT_PHONE);
options.addOption(OPT_LANGUAGE);
options.addOption(OPT_REQUIRE_CERTIFICATE);
options.addOption(OPT_CAN_LOGIN);
options.addOption(OPT_NEW_EMAIL);
options.addOption(OPT_NEW_NETID);
options.addOption("h", "help", false, "explain --modify options");
GnuParser parser = new GnuParser();
CommandLine command;
try {
command = parser.parse(options, argv);
} catch (ParseException e) {
System.err.println(e.getMessage());
return 1;
}
if (command.hasOption('h'))
{
new HelpFormatter().printHelp("user --modify [options]", options);
return 0;
}
// Modify!
EPerson eperson = null;
try {
if (command.hasOption(OPT_NETID.getOpt()))
{
eperson = findByNetid(context, command.getOptionValue(OPT_NETID.getOpt()));
}
else if (command.hasOption(OPT_EMAIL.getOpt()))
{
eperson = findByEmail(context, command.getOptionValue(OPT_EMAIL.getOpt()));
}
else
{
System.err.println("No EPerson selected");
return 1;
}
} catch (SQLException e) {
System.err.append(e.getMessage());
return 1;
} catch (AuthorizeException e) { /* XXX SNH */ }
boolean modified = false;
if (null == eperson)
{
System.err.println("No such EPerson");
return 1;
}
else
{
if (command.hasOption(OPT_NEW_EMAIL.getOpt()))
{
eperson.setEmail(command.getOptionValue(OPT_NEW_EMAIL.getOpt()));
modified = true;
}
if (command.hasOption(OPT_NEW_NETID.getOpt()))
{
eperson.setNetid(command.getOptionValue(OPT_NEW_NETID.getOpt()));
modified = true;
}
if (command.hasOption(OPT_GIVENNAME.getOpt()))
{
eperson.setFirstName(command.getOptionValue(OPT_GIVENNAME.getOpt()));
modified = true;
}
if (command.hasOption(OPT_SURNAME.getOpt()))
{
eperson.setLastName(command.getOptionValue(OPT_SURNAME.getOpt()));
modified = true;
}
if (command.hasOption(OPT_PHONE.getOpt()))
{
eperson.setMetadata("phone", command.getOptionValue(OPT_PHONE.getOpt()));
modified = true;
}
if (command.hasOption(OPT_LANGUAGE.getOpt()))
{
eperson.setLanguage(command.getOptionValue(OPT_LANGUAGE.getOpt()));
modified = true;
}
if (command.hasOption(OPT_REQUIRE_CERTIFICATE.getOpt()))
{
eperson.setRequireCertificate(Boolean.valueOf(command.getOptionValue(
OPT_REQUIRE_CERTIFICATE.getOpt())));
modified = true;
}
if (command.hasOption(OPT_CAN_LOGIN.getOpt()))
{
eperson.setCanLogIn(Boolean.valueOf(command.getOptionValue(OPT_CAN_LOGIN.getOpt())));
modified = true;
}
if (modified)
{
try {
eperson.update();
context.commit();
System.out.printf("Modified EPerson %d\n", eperson.getID());
} catch (SQLException ex) {
context.abort();
System.err.println(ex.getMessage());
return 1;
} catch (AuthorizeException ex) { /* XXX SNH */ }
}
else
{
System.out.println("No changes.");
}
}
return 0;
}
/** Command to list known EPersons. */
private static int cmdList(Context context, String[] argv)
{
// XXX ideas:
// specific user/netid
// wild or regex match user/netid
// select details (pseudo-format string)
try {
for (EPerson person : findAll(context, EMAIL))
{
System.out.printf("%d\t%s/%s\t%s, %s\n",
person.getID(),
person.getEmail(),
person.getNetid(),
person.getLastName(), person.getFirstName()); // TODO more user details
}
} catch (SQLException ex) {
System.err.println(ex.getMessage());
return 1;
}
return 0;
}
}