diff --git a/dspace-api/src/main/java/org/dspace/app/launcher/CommandRunner.java b/dspace-api/src/main/java/org/dspace/app/launcher/CommandRunner.java new file mode 100644 index 0000000000..259acf0fa0 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/launcher/CommandRunner.java @@ -0,0 +1,107 @@ +/** + * 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.app.launcher; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StreamTokenizer; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author mwood + */ +public class CommandRunner +{ + public static void main(String[] args) + throws FileNotFoundException, IOException + { + if (args.length > 0) + { + runManyCommands(args[0]); + } + else + { + runManyCommands("-"); + } + // There is no sensible way to use the status returned by runManyCommands(). + // If called from the command line then we would want to return it + // through System.exit(). But if called (normally) from ScriptLauncher, + // there is no way to return it and we don't want to interrupt + // ScriptLauncher. + // + // "'tis a puzzlement." -- the King of Siam + } + + /** + * Read a file of command lines and execute each in turn. + * + * @param doc details of recognized commands. + * @param script the file of command lines to be executed. + * @return + * @throws FileNotFoundException + * @throws IOException + */ + static int runManyCommands(String script) + throws FileNotFoundException, IOException + { + Reader input; + if ("-".equals(script)) + { + input = new InputStreamReader(System.in); + } + else + { + input = new FileReader(script); + } + + StreamTokenizer tokenizer = new StreamTokenizer(input); + + tokenizer.eolIsSignificant(true); + + tokenizer.ordinaryChar('-'); + tokenizer.wordChars('-', '-'); + + tokenizer.ordinaryChars('0', '9'); + tokenizer.wordChars('0', '9'); + + tokenizer.ordinaryChar('.'); + tokenizer.wordChars('.', '.'); + + tokenizer.ordinaryChar('@'); + tokenizer.wordChars('@', '@'); + + int status = 0; + List tokens = new ArrayList(); + while (StreamTokenizer.TT_EOF != tokenizer.nextToken()) + { + if (StreamTokenizer.TT_EOL == tokenizer.ttype) + { + if (tokens.size() > 0) + { + status = ScriptLauncher.runOneCommand(tokens.toArray(new String[tokens.size()])); + if (status > 0) + { + break; + } + tokens.clear(); + } + } + else + { + tokens.add(tokenizer.sval); + } + } + + return status; + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java b/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java index e912038b89..202c877346 100644 --- a/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java +++ b/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java @@ -7,6 +7,10 @@ */ package org.dspace.app.launcher; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.List; import org.dspace.core.ConfigurationManager; import org.dspace.servicemanager.DSpaceKernelImpl; import org.dspace.servicemanager.DSpaceKernelInit; @@ -14,8 +18,6 @@ import org.dspace.services.RequestService; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; -import java.util.List; -import java.lang.reflect.Method; /** * A DSpace script launcher. @@ -28,12 +30,16 @@ public class ScriptLauncher /** The service manager kernel */ private static transient DSpaceKernelImpl kernelImpl; + /** Definitions of all commands. */ + private static final Document commandConfigs = getConfig(); + /** * Execute the DSpace script launcher * * @param args Any parameters required to be passed to the scripts it executes */ public static void main(String[] args) + throws FileNotFoundException, IOException { // Check that there is at least one argument if (args.length < 1) @@ -66,156 +72,9 @@ public class ScriptLauncher throw new IllegalStateException(message, e); } - // Parse the configuration file looking for the command entered - Document doc = getConfig(); - String request = args[0]; - Element root = doc.getRootElement(); - List commands = root.getChildren("command"); - for (Element command : commands) - { - if (request.equalsIgnoreCase(command.getChild("name").getValue())) - { - // Run each step - List steps = command.getChildren("step"); - for (Element step : steps) - { - // Instantiate the class - Class target = null; - - // Is it the special case 'dsrun' where the user provides the class name? - String className; - if ("dsrun".equals(request)) - { - if (args.length < 2) - { - System.err.println("Error in launcher.xml: Missing class name"); - System.exit(1); - } - className = args[1]; - } - else { - className = step.getChild("class").getValue(); - } - try - { - target = Class.forName(className, - true, - Thread.currentThread().getContextClassLoader()); - } - catch (ClassNotFoundException e) - { - System.err.println("Error in launcher.xml: Invalid class name: " + className); - System.exit(1); - } - - // Strip the leading argument from the args, and add the arguments - // Set false if the arguments should not be passed on - String[] useargs = args.clone(); - Class[] argTypes = {useargs.getClass()}; - boolean passargs = true; - if ((step.getAttribute("passuserargs") != null) && - ("false".equalsIgnoreCase(step.getAttribute("passuserargs").getValue()))) - { - passargs = false; - } - if ((args.length == 1) || (("dsrun".equals(request)) && (args.length == 2)) || (!passargs)) - { - useargs = new String[0]; - } - else - { - // The number of arguments to ignore - // If dsrun is the command, ignore the next, as it is the class name not an arg - int x = 1; - if ("dsrun".equals(request)) - { - x = 2; - } - String[] argsnew = new String[useargs.length - x]; - for (int i = x; i < useargs.length; i++) - { - argsnew[i - x] = useargs[i]; - } - useargs = argsnew; - } - - // Add any extra properties - List bits = step.getChildren("argument"); - if (step.getChild("argument") != null) - { - String[] argsnew = new String[useargs.length + bits.size()]; - int i = 0; - for (Element arg : bits) - { - argsnew[i++] = arg.getValue(); - } - for (; i < bits.size() + useargs.length; i++) - { - argsnew[i] = useargs[i - bits.size()]; - } - useargs = argsnew; - } - - // Establish the request service startup - RequestService requestService = kernelImpl.getServiceManager().getServiceByName(RequestService.class.getName(), RequestService.class); - if (requestService == null) { - throw new IllegalStateException("Could not get the DSpace RequestService to start the request transaction"); - } - - // Establish a request related to the current session - // that will trigger the various request listeners - requestService.startRequest(); - - // Run the main() method - try - { - Object[] arguments = {useargs}; - - // Useful for debugging, so left in the code... - /**System.out.print("About to execute: " + className); - for (String param : useargs) - { - System.out.print(" " + param); - } - System.out.println("");**/ - - Method main = target.getMethod("main", argTypes); - main.invoke(null, arguments); - - // ensure we close out the request (happy request) - requestService.endRequest(null); - } - catch (Exception e) - { - // Failure occurred in the request so we destroy it - requestService.endRequest(e); - - if (kernelImpl != null) - { - kernelImpl.destroy(); - kernelImpl = null; - } - - // Exceptions from the script are reported as a 'cause' - Throwable cause = e.getCause(); - System.err.println("Exception: " + cause.getMessage()); - cause.printStackTrace(); - System.exit(1); - } - - } - - // Destroy the service kernel - if (kernelImpl != null) - { - kernelImpl.destroy(); - kernelImpl = null; - } - - // Everything completed OK - System.exit(0); - } - } + // Look up command in the configuration, and execute. + int status; + status = runOneCommand(args); // Destroy the service kernel if it is still alive if (kernelImpl != null) @@ -224,10 +83,165 @@ public class ScriptLauncher kernelImpl = null; } - // The command wasn't found - System.err.println("Command not found: " + args[0]); - display(); - System.exit(1); + System.exit(status); + } + + /** + * Recognize and execute a single command. + * @param doc + * @param args + */ + static int runOneCommand(String[] args) + { + String request = args[0]; + Element root = commandConfigs.getRootElement(); + List commands = root.getChildren("command"); + Element command = null; + for (Element candidate : commands) + { + if (request.equalsIgnoreCase(candidate.getChild("name").getValue())) + { + command = candidate; + break; + } + } + + if (null == command) + { + // The command wasn't found + System.err.println("Command not found: " + args[0]); + display(); + return 1; + } + + // Run each step + List steps = command.getChildren("step"); + for (Element step : steps) + { + // Instantiate the class + Class target = null; + + // Is it the special case 'dsrun' where the user provides the class name? + String className; + if ("dsrun".equals(request)) + { + if (args.length < 2) + { + System.err.println("Error in launcher.xml: Missing class name"); + return 1; + } + className = args[1]; + } + else { + className = step.getChild("class").getValue(); + } + try + { + target = Class.forName(className, + true, + Thread.currentThread().getContextClassLoader()); + } + catch (ClassNotFoundException e) + { + System.err.println("Error in launcher.xml: Invalid class name: " + className); + return 1; + } + + // Strip the leading argument from the args, and add the arguments + // Set false if the arguments should not be passed on + String[] useargs = args.clone(); + Class[] argTypes = {useargs.getClass()}; + boolean passargs = true; + if ((step.getAttribute("passuserargs") != null) && + ("false".equalsIgnoreCase(step.getAttribute("passuserargs").getValue()))) + { + passargs = false; + } + if ((args.length == 1) || (("dsrun".equals(request)) && (args.length == 2)) || (!passargs)) + { + useargs = new String[0]; + } + else + { + // The number of arguments to ignore + // If dsrun is the command, ignore the next, as it is the class name not an arg + int x = 1; + if ("dsrun".equals(request)) + { + x = 2; + } + String[] argsnew = new String[useargs.length - x]; + for (int i = x; i < useargs.length; i++) + { + argsnew[i - x] = useargs[i]; + } + useargs = argsnew; + } + + // Add any extra properties + List bits = step.getChildren("argument"); + if (step.getChild("argument") != null) + { + String[] argsnew = new String[useargs.length + bits.size()]; + int i = 0; + for (Element arg : bits) + { + argsnew[i++] = arg.getValue(); + } + for (; i < bits.size() + useargs.length; i++) + { + argsnew[i] = useargs[i - bits.size()]; + } + useargs = argsnew; + } + + // Establish the request service startup + RequestService requestService = kernelImpl.getServiceManager().getServiceByName( + RequestService.class.getName(), RequestService.class); + if (requestService == null) + { + throw new IllegalStateException( + "Could not get the DSpace RequestService to start the request transaction"); + } + + // Establish a request related to the current session + // that will trigger the various request listeners + requestService.startRequest(); + + // Run the main() method + try + { + Object[] arguments = {useargs}; + + // Useful for debugging, so left in the code... + /**System.out.print("About to execute: " + className); + for (String param : useargs) + { + System.out.print(" " + param); + } + System.out.println("");**/ + + Method main = target.getMethod("main", argTypes); + main.invoke(null, arguments); + + // ensure we close out the request (happy request) + requestService.endRequest(null); + } + catch (Exception e) + { + // Failure occurred in the request so we destroy it + requestService.endRequest(e); + + // Exceptions from the script are reported as a 'cause' + Throwable cause = e.getCause(); + System.err.println("Exception: " + cause.getMessage()); + cause.printStackTrace(); + return 1; + } + } + + // Everything completed OK + return 0; } /** @@ -261,8 +275,7 @@ public class ScriptLauncher */ private static void display() { - Document doc = getConfig(); - List commands = doc.getRootElement().getChildren("command"); + List commands = commandConfigs.getRootElement().getChildren("command"); System.out.println("Usage: dspace [command-name] {parameters}"); for (Element command : commands) { diff --git a/dspace-api/src/main/java/org/dspace/eperson/EPerson.java b/dspace-api/src/main/java/org/dspace/eperson/EPerson.java index 6113eab5ac..4ac7811269 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/EPerson.java +++ b/dspace-api/src/main/java/org/dspace/eperson/EPerson.java @@ -11,6 +11,15 @@ 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.CommandLineParser; +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; @@ -1173,6 +1182,7 @@ public class EPerson extends DSpaceObject } } + @Override public String getName() { return getEmail(); @@ -1184,4 +1194,415 @@ public class EPerson extends DSpaceObject } + /* + * 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 + { + 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) + { + 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) + { + 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; + } } diff --git a/dspace/config/launcher.xml b/dspace/config/launcher.xml index 21b64d0332..a84cca1af8 100644 --- a/dspace/config/launcher.xml +++ b/dspace/config/launcher.xml @@ -215,6 +215,14 @@ + + read + Execute a stream of 'dspace' commands from a file or pipe + + org.dspace.app.launcher.CommandRunner + + + stat-general Compile the general statistics @@ -371,6 +379,14 @@ + + user + Manipulate a normal user account + + org.dspace.eperson.EPerson + + + migrate-embargo Embargo manager tool used to migrate old version of Embargo to the new one included in dspace3 diff --git a/pom.xml b/pom.xml index 6176ca010c..ccb83d5408 100644 --- a/pom.xml +++ b/pom.xml @@ -648,7 +648,7 @@ commons-cli commons-cli - 1.0 + 1.2 commons-codec