/* * ScriptLauncher.java * * Version: $Revision$ * * Date: $Date$ * * Copyright (c) 2002-2009, Duraspace. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Duraspace nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.dspace.app.launcher; import org.dspace.core.ConfigurationManager; import org.dspace.servicemanager.DSpaceKernelImpl; import org.dspace.servicemanager.DSpaceKernelInit; 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. * * @author Stuart Lewis * @author Mark Diggory */ public class ScriptLauncher { /** The service manager kernel */ private static transient DSpaceKernelImpl kernelImpl; /** * Execute the DSpace script launcher * * @param args Any parameters required to be passed to the scripts it executes * @throws Exception */ public static void main(String[] args) { // Check that there is at least one argument if (args.length < 1) { System.err.println("You must provide at least one command argument"); display(); System.exit(1); } // Initalise the service manager kernel try { kernelImpl = DSpaceKernelInit.getKernel(null); if (!kernelImpl.isRunning()) { kernelImpl.start(ConfigurationManager.getProperty("dspace.dir")); } } catch (Exception e) { // Failed to start so destroy it and log and throw an exception try { kernelImpl.destroy(); } catch (Exception e1) { // Nothing to do } String message = "Failure during filter init: " + e.getMessage(); System.err.println(message + ":" + e); throw new RuntimeException(message, e); } // Parse the configuration file looking for the command entered Document doc = getConfig(); String request = args[0]; Element root = doc.getRootElement(); List<Element> commands = root.getChildren("command"); for (Element command : commands) { if (request.equalsIgnoreCase(command.getChild("name").getValue())) { // Run each step List<Element> 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 <passargs>false</passargs> 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<Element> 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); Object output = 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; } System.exit(0); } } // Destroy the service kernel if it is still alive if (kernelImpl != null) { kernelImpl.destroy(); kernelImpl = null; } // The command wasn't found System.err.println("Command not found: " + args[0]); display(); System.exit(1); } /** * Load the launcher configuration file * * @return The XML configuration file Document */ private static Document getConfig() { // Load the launcher configuration file String config = ConfigurationManager.getProperty("dspace.dir") + System.getProperty("file.separator") + "config" + System.getProperty("file.separator") + "launcher.xml"; SAXBuilder saxBuilder = new SAXBuilder(); Document doc = null; try { doc = saxBuilder.build(config); } catch (Exception e) { System.err.println("Unable to load the launcher configuration file: [dspace]/config/launcher.xml"); System.err.println(e.getMessage()); System.exit(1); } return doc; } /** * Display the commands that the current launcher config file knows about */ private static void display() { Document doc = getConfig(); List<Element> commands = doc.getRootElement().getChildren("command"); System.out.println("Usage: dspace [command-name] {parameters}"); for (Element command : commands) { System.out.println(" - " + command.getChild("name").getValue() + ": " + command.getChild("description").getValue()); } } }