Package

Source Code of LNISmokeTest

/*
* LNISmokeTest.java
*
* Version: $Revision: 3705 $
*
* Date: $Date: 2009-04-11 17:02:24 +0000 (Sat, 11 Apr 2009) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology.  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 the Hewlett-Packard Company nor the name of the
* Massachusetts Institute of Technology nor the names of their
* 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.
*/

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
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.PosixParser;
import org.apache.commons.codec.binary.Base64;
import org.dspace.app.dav.client.LNIClientUtils;
import org.dspace.app.dav.client.LNISoapServlet;
import org.dspace.app.dav.client.LNISoapServletServiceLocator;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.JDOMParseException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;


/**
* Very simple test program for DSpace Lightweight Network Interface (LNI).
* <p>
* This will test and demonstrate the LNI's SOAP API and some WebDAV operations.
* It was written as a simple "smoke" test for the LNI to exercise basic
* features in a simple way, and to serve as a coding example.
*
* Example: (SOAP endpoint is http://mydspace.edu/dspace-lni/DSpaceLNI )
*
* /dspace/bin/dsrun LNISmokeTest \ -e
* http://user:passwd@mydsapce.edu/dspace-lni/DSpaceLNI \ -f 123.45/67
*
* @author Larry Stone
* @version $Revision: 3705 $
*/
public class LNISmokeTest
{

    /**
     * The Constant NS_DAV.
     * namespace for DAV XML objects
     */
    private static final Namespace NS_DAV = Namespace.getNamespace("DAV:");

    /**
     * The Constant NS_DSPACE.
     * DSpace's XML namespace
     */
    private static final Namespace NS_DSPACE = Namespace.getNamespace("dspace",
            "http://www.dspace.org/xmlns/dspace");

    /** The output pretty. */
    private static XMLOutputter outputPretty = new XMLOutputter(Format
            .getPrettyFormat());

    // XML expressions for propfind calls (below)
   
    /** The Constant allProp. */
    private static final String allProp = "<propfind xmlns=\"DAV:\"><allprop /></propfind>";

    /** The Constant nameProp. */
    private static final String nameProp = "<propfind xmlns=\"DAV:\"><propname /></propfind>";

    /** The Constant someProp. */
    private static final String someProp = "<propfind xmlns=\"DAV:\"><prop>"
            + "<displayname/>"
            + "<dspace:type xmlns:dspace=\"http://www.dspace.org/xmlns/dspace\" />"
            + "</prop></propfind>";

    /** The Constant specificPropPrefix. */
    private static final String specificPropPrefix = "<propfind xmlns=\"DAV:\""
            + " xmlns:dspace=\"http://www.dspace.org/xmlns/dspace\">"
            + "  <prop><";

    /** The Constant specificPropSuffix. */
    private static final String specificPropSuffix = "/></prop></propfind>";

    /**
     * Usage. prints usage info to System.out & dies.
     *
     * @param options the options
     * @param status the status
     * @param msg the msg
     */
    private static void Usage(Options options, int status, String msg)
    {
        HelpFormatter hf = new HelpFormatter();
        if (msg != null)
        {
            System.out.println(msg + "\n");
        }
        hf.printHelp("LNISmokeTest\n" + "       -e SOAP-endpoint-URL\n"
                + "       [ -s collection-handle -P package -i path ] |\n"
                + "       [ -d item-handle -P package -o path ] |\n"
                + "       [ -f handle [ -N propertyName ] ] |\n"
                + "       [ -r handle [ -N propertyName ] ] |\n"
                + "       [ -n handle ] |\n"
                + "       [ -p handle  -N propertyName -V newvalue ] |\n"
                + "       [ -d item-handle -C collection-handle ]\n", options,
                false);
        System.exit(status);
    }

    /**
     * Execute command line. See Usage string for options and arguments.
     *
     * @param argv the argv
     *
     * @throws Exception the exception
     */
    public static void main(String[] argv) throws Exception
    {
        Options options = new Options();

        OptionGroup func = new OptionGroup();
        func.addOption(new Option("c", "copy", true,
                "copy <Item> to -C <Collection>"));
        func.addOption(new Option("s", "submit", true,
                "submit <collection> -P <packager> -i <file>"));
        func.addOption(new Option("d", "disseminate", true,
                "disseminate <item> -P <packager> -o <file>"));
        func.addOption(new Option("f", "propfind", true,
                "propfind of all properties or -N <propname>"));
        func.addOption(new Option("r", "rpropfind", true,
                "recursive propfind, only collections"));
        func.addOption(new Option("n", "names", true,
                "list all property names on resource"));
        func.addOption(new Option("p", "proppatch", true,
                "set property: <handle> -N <property> -V <newvalue>"));
        func.setRequired(true);
        options.addOptionGroup(func);

        options.addOption("h", "help", false, "show help message");
        options
                .addOption("e", "endpoint", true,
                        "SOAP endpoint URL (REQUIRED)");
        options.addOption("P", "packager", true,
                "Packager to use to import/export a package.");
        options.addOption("C", "collection", true,
                "Target collection of -c copy");
        options
                .addOption("o", "output", true,
                        "file to create for new package");
        options.addOption("i", "input", true,
                "file containing package to submit");
        options.addOption("N", "name", true, "name of property to query/set");
        options.addOption("V", "value", true,
                "new value for property being set");

        try
        {
            CommandLine line = (new PosixParser()).parse(options, argv);
            if (line.hasOption("h"))
            {
                Usage(options, 0, null);
            }

            // get SOAP client connection, using the endpoint URL
            String endpoint = line.getOptionValue("e");
            if (endpoint == null)
            {
                Usage(options, 2, "Missing the required -e endpoint argument");
            }
            LNISoapServletServiceLocator loc = new LNISoapServletServiceLocator();
            LNISoapServlet lni = loc.getDSpaceLNI(new URL(endpoint));

            // propfind - with optional single-property Name
            if (line.hasOption("f"))
            {
                String pfXml = (line.hasOption("N")) ? specificPropPrefix
                        + line.getOptionValue("N") + specificPropSuffix
                        : allProp;
                doPropfind(lni, line.getOptionValue("f"), pfXml, 0, null);
            }

            // recursive propfind limited to collection, community objects
            else if (line.hasOption("r"))
            {
                doPropfind(lni, line.getOptionValue("r"), someProp, -1,
                        "collection,community");
            }
            else if (line.hasOption("n"))
            {
                doPropfind(lni, line.getOptionValue("n"), nameProp, 0, null);
            }
            else if (line.hasOption("p"))
            {
                if (line.hasOption("N") && line.hasOption("V"))
                {
                    doProppatch(lni, line.getOptionValue("p"), line
                            .getOptionValue("N"), line.getOptionValue("V"));
                }
                else
                {
                    Usage(options, 13,
                            "Missing required args: -N <name> -V <value>n");
                }
            }

            // submit a package
            else if (line.hasOption("s"))
            {
                if (line.hasOption("P") && line.hasOption("i"))
                {
                    doPut(lni, line.getOptionValue("s"), line
                            .getOptionValue("P"), line.getOptionValue("i"),
                            endpoint);
                }
                else
                {
                    Usage(options, 13,
                            "Missing required args after -s: -P <packager> -i <file>");
                }
            }

            // Disseminate (GET) item as package
            else if (line.hasOption("d"))
            {
                if (line.hasOption("P") && line.hasOption("o"))
                {
                    doGet(lni, line.getOptionValue("d"), line
                            .getOptionValue("P"), line.getOptionValue("o"),
                            endpoint);
                }
                else
                {
                    Usage(options, 13,
                            "Missing required args after -d: -P <packager> -o <file>");
                }
            }

            // copy from src to dst
            else if (line.hasOption("c"))
            {
                if (line.hasOption("C"))
                {
                    doCopy(lni, line.getOptionValue("c"), line
                            .getOptionValue("C"));
                }
                else
                {
                    Usage(options, 13,
                            "Missing required args after -c: -C <collection>\n");
                }
            }
            else
            {
                Usage(options, 14, "Missing command option.\n");
            }

        }
        catch (ParseException pe)
        {
            Usage(options, 1, "Error in arguments: " + pe.toString());
           
        }
        catch (java.rmi.RemoteException de)
        {
            System.out.println("ERROR, got RemoteException, message="
                    + de.getMessage());
           
            de.printStackTrace();
           
            die(1, "  Exception class=" + de.getClass().getName());
        }
    }

    /**
     * Die.
     *
     * @param exit the exit
     * @param msg the msg
     */
    private static void die(int exit, String msg)
    {
        System.err.println(msg);
        System.exit(exit);
    }

    // Like LNI lookup(), but dies on error so we don't have to check result.
    // Also interprets the special format "handle bitstream" (with space
    // separating the words) as the ``handle'' of a bitstream -- a combination
    // of Item handle and bitstream sequence-ID.
    // On success it returns a DAV resource URI, relative to the
    // root of the DAV resource hierarchy, e.g. "/dso_12345.678$123"
    /**
     * Do lookup.
     *
     * @param lni the lni
     * @param handle the handle
     * @param bitstream the bitstream
     *
     * @return the string
     *
     * @throws RemoteException the remote exception
     */
    private static String doLookup(LNISoapServlet lni, String handle,
            String bitstream) throws java.rmi.RemoteException
    {
        // hack: if "handle" starts with '/' and there is no bitstream
        // assume it is URI passed in and just return that.
        if (handle.startsWith("/") && bitstream == null)
        {
            return handle;
        }

        // hack: parse "handle bitstream" syntax of handle.
        if (handle.indexOf(" ") >= 0 && bitstream == null)
        {
            String h[] = handle.split("\\s+");
            handle = h[0];
            bitstream = h[1];
        }

        String uri = lni.lookup(handle, bitstream);
        if (uri == null)
        {
            die(2, "ERROR, got null from lookup(\"" + handle + "\")");
        }
        System.out.println("DEBUG: lookup returns: \"" + uri + "\"");
        return uri;
    }

    /**
     * Do propfind.
     *
     * @param lni the lni
     * @param handle the handle
     * @param pf the pf
     * @param depth the depth
     * @param types the types
     *
     * @throws RemoteException the remote exception
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private static void doPropfind(LNISoapServlet lni, String handle,
            String pf, int depth, String types)
            throws java.rmi.RemoteException, java.io.IOException
    {
        String uri = doLookup(lni, handle, null);
        String result = lni.propfind(uri, pf, depth, types);
        try
        {
            SAXBuilder builder = new SAXBuilder();
            Document msDoc = builder.build(new java.io.StringReader(result));
            Element ms = msDoc.getRootElement();
            ListIterator ri = ms.getChildren("response", NS_DAV).listIterator();
            while (ri.hasNext())
            {
                Element resp = (Element) ri.next();
                String href = resp.getChildText("href", NS_DAV);
                System.out.println("Resource = " + href);
                ListIterator pi = resp.getChildren("propstat", NS_DAV)
                        .listIterator();
                while (pi.hasNext())
                {
                    Element ps = (Element) pi.next();
                    String status = ps.getChildText("status", NS_DAV);
                    if (status.indexOf("200") >= 0)
                    {
                        System.out
                                .println("  === PROPERTIES Successfully returned:");
                    }
                    else
                    {
                        System.out.println("  === PROPERTIES with Status="
                                + status);
                    }
                    // print properties and values
                    Element prop = ps.getChild("prop", NS_DAV);
                    ListIterator ppi = prop.getChildren().listIterator();
                    while (ppi.hasNext())
                    {
                        Element e = (Element) ppi.next();
                        String value = e.getTextTrim();
                        if (value.equals(""))
                        {
                            List kids = e.getChildren();
                            if (kids.size() > 0)
                            {
                                value = outputPretty.outputString(kids);
                            }
                            if (value.indexOf("\n") >= 0)
                            {
                                value = "\n" + value;
                            }
                        }
                        else
                        {
                            value = "\"" + value + "\"";
                        }
                        String equals = value.equals("") ? "" : " = ";
                        System.out.println("    " + e.getQualifiedName()
                                + equals + value);
                    }
                }
            }

        }
        catch (JDOMParseException je)
        {
            je.printStackTrace();
           
            die(3, "ERROR: " + je.toString());
        }
        catch (JDOMException je)
        {
            je.printStackTrace();
           
            die(4, "ERROR: " + je.toString());
        }

    }

    /**
     * Do proppatch.
     *
     * @param lni the lni
     * @param handle the handle
     * @param prop the prop
     * @param val the val
     *
     * @throws RemoteException the remote exception
     */
    private static void doProppatch(LNISoapServlet lni, String handle,
            String prop, String val) throws java.rmi.RemoteException
    {
        String uri = doLookup(lni, handle, null);
        String action = (val.length() > 0) ? "set" : "remove";
        String pupdate = "<propertyupdate xmlns=\"DAV:\" xmlns:dspace=\"http://www.dspace.org/xmlns/dspace\">"
                + "<"
                + action
                + "><prop><"
                + prop
                + ">"
                + val
                + "</"
                + prop
                + "></prop></" + action + "></propertyupdate>";
        System.err.println("DEBUG: sending: " + pupdate);
        String result = lni.proppatch(uri, pupdate);
        System.err.println("RESULT: " + result);
    }

    // "copy" src item into dst collection, both are handles.
    /**
     * Do copy.
     *
     * @param lni the lni
     * @param src the src
     * @param dst the dst
     *
     * @throws RemoteException the remote exception
     */
    private static void doCopy(LNISoapServlet lni, String src, String dst)
            throws java.rmi.RemoteException
    {
        String srcUri = doLookup(lni, src, null);
        String dstUri = doLookup(lni, dst, null);
        int status = lni.copy(srcUri, dstUri, -1, false, true);
        System.err.println("Copy status = " + String.valueOf(status));
    }

    /**
     * Implement WebDAV PUT http request.
     *
     * This might be simpler with a real HTTP client library, but
     * java.net.HttpURLConnection is part of the standard SDK and it
     * demonstrates the concepts.
     *
     * @param lni the lni
     * @param collHandle the coll handle
     * @param packager the packager
     * @param source the source
     * @param endpoint the endpoint
     *
     * @throws RemoteException the remote exception
     * @throws ProtocolException the protocol exception
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws FileNotFoundException the file not found exception
     */
    private static void doPut(LNISoapServlet lni, String collHandle,
            String packager, String source, String endpoint)
            throws java.rmi.RemoteException, ProtocolException, IOException,
            FileNotFoundException
    {
        // assemble URL from chopped endpoint-URL and relative URI
        String collURI = doLookup(lni, collHandle, null);
        URL url = LNIClientUtils.makeDAVURL(endpoint, collURI, packager);
        System.err.println("DEBUG: PUT file=" + source + " to URL="
                + url.toString());

        // connect with PUT method, then copy file over.
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("PUT");
        conn.setDoOutput(true);
        fixBasicAuth(url, conn);
        conn.connect();

        InputStream in = new FileInputStream(source);
        OutputStream out = conn.getOutputStream();
        try {
            copyStream(in, out);
        } finally {
            in.close();
            out.close();
        }

        int status = conn.getResponseCode();
        if (status < 200 || status >= 300)
        {
            die(status, "HTTP error, status=" + String.valueOf(status)
                    + ", message=" + conn.getResponseMessage());
        }

        // diagnostics, and get resulting new item's location if avail.
        System.err.println("DEBUG: sent " + source);
        System.err.println("RESULT: Status="
                + String.valueOf(conn.getResponseCode()) + " "
                + conn.getResponseMessage());
        String loc = conn.getHeaderField("Location");
        System.err.println("RESULT: Location="
                + ((loc == null) ? "NULL!" : loc));
    }

    /**
     * Get an item with WebDAV GET http request.
     *
     * @param lni the lni
     * @param itemHandle the item handle
     * @param packager the packager
     * @param output the output
     * @param endpoint the endpoint
     *
     * @throws RemoteException the remote exception
     * @throws ProtocolException the protocol exception
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws FileNotFoundException the file not found exception
     */
    private static void doGet(LNISoapServlet lni, String itemHandle,
            String packager, String output, String endpoint)
            throws java.rmi.RemoteException, ProtocolException, IOException,
            FileNotFoundException
    {
        // assemble URL from chopped endpoint-URL and relative URI
        String itemURI = doLookup(lni, itemHandle, null);
        URL url = LNIClientUtils.makeDAVURL(endpoint, itemURI, packager);
        System.err.println("DEBUG: GET from URL: " + url.toString());

        // connect with GET method, then copy file over.
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        fixBasicAuth(url, conn);
        conn.connect();
        int status = conn.getResponseCode();
        if (status < 200 || status >= 300)
        {
            die(status, "HTTP error, status=" + String.valueOf(status)
                    + ", message=" + conn.getResponseMessage());
        }

        InputStream in = conn.getInputStream();
        OutputStream out = new FileOutputStream(output);
        copyStream(in, out);
        in.close();
        out.close();

        System.err.println("DEBUG: Created local file " + output);
        System.err.println("RESULT: Status="
                + String.valueOf(conn.getResponseCode()) + " "
                + conn.getResponseMessage());
    }

    //
    /**
     * Fix basic auth.
     *
     * Set up HTTP basic authentication based on user/password in URL.
     * The HttpURLConnection class should do this itself!
     *
     * @param url the url
     * @param conn the conn
     */
    private static void fixBasicAuth(URL url, HttpURLConnection conn)
    {
        String userinfo = url.getUserInfo();
        if (userinfo != null)
        {
            String cui = new String(Base64.encodeBase64(userinfo.getBytes()));
            conn.addRequestProperty("Authorization", "Basic " + cui);
            System.err.println("DEBUG: Sending Basic auth=" + cui);
        }
    }

    /**
     * Copy stream. copy from one stream to another
     *
     * @param input the input
     * @param output the output
     *
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private static void copyStream(final InputStream input,
            final OutputStream output) throws IOException
    {
        final int BUFFER_SIZE = 1024 * 4;
        final byte[] buffer = new byte[BUFFER_SIZE];

        while (true)
        {
            final int count = input.read(buffer, 0, BUFFER_SIZE);
            if (-1 == count)
            {
                break;
            }
            output.write(buffer, 0, count);
        }
    }
}
TOP

Related Classes of LNISmokeTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.