edu.caltech.ipac.firefly.server.WorkspaceManager.java Source code

Java tutorial

Introduction

Here is the source code for edu.caltech.ipac.firefly.server.WorkspaceManager.java

Source

/*
 * License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
 */
package edu.caltech.ipac.firefly.server;

import edu.caltech.ipac.firefly.data.WspaceMeta;
import edu.caltech.ipac.firefly.server.network.HttpServices;
import edu.caltech.ipac.firefly.server.util.Logger;
import edu.caltech.ipac.util.AppProperties;
import edu.caltech.ipac.util.StringUtils;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.client.methods.DavMethod;
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod;
import org.apache.jackrabbit.webdav.client.methods.PutMethod;
import org.apache.jackrabbit.webdav.property.DavProperty;
import org.apache.jackrabbit.webdav.property.DavPropertyName;
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
import org.apache.jackrabbit.webdav.property.DavPropertySet;
import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
import org.apache.jackrabbit.webdav.xml.Namespace;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Map;

/**
 * Date: 6/12/14
 *
 * @author loi
 * @version $Id: $
 */
public class WorkspaceManager {
    public static final String SEARCH_DIR = WspaceMeta.SEARCH_DIR;
    public static final String STAGING_DIR = WspaceMeta.STAGING_DIR;
    public static final String WS_ROOT_DIR = AppProperties.getProperty("workspace.root.dir", "/work");
    public static final String WS_HOST_URL = AppProperties.getProperty("workspace.host.url",
            "https://irsa.ipac.caltech.edu");

    private static final Namespace IRSA_NS = Namespace.getNamespace("irsa",
            "http://irsa.ipac.caltech.edu/namespace/");
    private static final Logger.LoggerImpl LOG = Logger.getLogger();

    public enum Partition {
        PUBSPACE, SSOSPACE;
        public String toString() {
            return name().toLowerCase();
        }
    }

    private Partition partition;
    private String userHome;
    private Map<String, String> cookies;

    public WorkspaceManager(String pubspaceId) {
        this(Partition.PUBSPACE, pubspaceId, null);
    }

    public WorkspaceManager(String ssospaceId, Map<String, String> cookies) {
        this(Partition.SSOSPACE, ssospaceId, cookies);

    }

    public WorkspaceManager(Partition partition, String wsId, Map<String, String> cookies) {
        this.partition = partition;
        this.userHome = WspaceMeta.ensureWsHomePath(wsId);
        this.cookies = cookies;
        davMakeDir("");
    }

    /**
     * returns the local filesystem path of the given relpath.
     * @param relPath  relative to the user's workspace and must starts with '/'
     * @return
     */
    public String getLocalFsPath(String relPath) {
        return WS_ROOT_DIR + getAbsPath(relPath);
    }

    /**
     * returns the webdav's absolute path.  for IRSA, it's /partition/user_ws/relpath.
     * @param relPath  relative to the user's workspace and must starts with '/'
     * @return
     */
    public String getAbsPath(String relPath) {
        String s = WspaceMeta.ensureRelPath(relPath);
        return getWsHome() + s;
    }

    /**
     * returns the relative path given the file.  for IRSA, it's /partition/user_ws/relpath.
     * @param file  relative to the user's workspace and must starts with '/'
     * @return
     */
    public String getRelPath(File file) {
        String s = file.getAbsolutePath().replaceFirst(WS_ROOT_DIR, "");
        s = s.replaceFirst(getWsHome(), "");
        return s;
    }

    /**
     * return the url of this resource.
     * @param relPath
     * @return
     */
    public String getResourceUrl(String relPath) {
        return WS_HOST_URL + getAbsPath(relPath);
    }

    public String getWsHome() {
        return "/" + partition + userHome;
    }

    public File createFile(String parent, String fname, String fext) {
        davMakeDir(parent);
        return new File(new File(getLocalFsPath(parent)),
                fname + "-" + System.currentTimeMillis() % 1000000 + fext);
    }

    /**
     * convenience method to create meta for a local file in the workspace
     * @param file
     * @param propName
     * @param value
     * @return
     */
    public WspaceMeta newMeta(File file, String propName, String value) {
        WspaceMeta meta = new WspaceMeta(getWsHome(), getRelPath(file));
        meta.setProperty(propName, value);
        return meta;
    }

    //====================================================================
    //  WEBDAV functions
    //====================================================================

    /**
     * create a directory given by the relPath parameter.
     * @param relPath relative to the user's workspace
     * @return  the absolute path to the directory on the filesystem.
     */
    public File davMakeDir(String relPath) {
        try {
            String[] parts = relPath.split("/");
            String cdir = "/";
            for (String s : parts) {
                cdir += StringUtils.isEmpty(s) ? "" : s + "/";
                WspaceMeta m = getMeta(cdir, WspaceMeta.Includes.NONE);
                if (m == null) {
                    DavMethod mkcol = new MkColMethod(getResourceUrl(cdir));
                    if (!executeMethod(mkcol)) {
                        // handle error
                        System.out
                                .println("Unable to create directory:" + relPath + " -- " + mkcol.getStatusText());
                        return null;
                    }
                }
            }
            return new File(getLocalFsPath(relPath));
        } catch (Exception e) {
            LOG.error(e, "Error while makeCollection:" + relPath);
        }
        return null;
    }

    public boolean davPut(File upload, String toPath) {
        try {
            PutMethod put = new PutMethod(getResourceUrl(toPath));
            RequestEntity requestEntity = new InputStreamRequestEntity(
                    new BufferedInputStream(new FileInputStream(upload), HttpServices.BUFFER_SIZE),
                    upload.length());
            put.setRequestEntity(requestEntity);
            /** is to allow a client that is sending a request message with a request body
             *  to determine if the origin server is willing to accept the request
             * (based on the request headers) before the client sends the request body.
             * this require server supporting HTTP/1.1 protocol.
             */
            put.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, true);

            if (!executeMethod(put)) {
                // handle error
                System.out.println("Unable to upload file:" + toPath + " -- " + put.getStatusText());
                return false;
            }

            return true;
        } catch (Exception e) {
            LOG.error(e, "Error while uploading file:" + upload.getPath());
        }
        return false;
    }

    //====================================================================
    //  for firefly use
    //====================================================================

    public WspaceMeta getMeta(String relPath) {
        return getMeta(relPath, WspaceMeta.Includes.ALL);
    }

    public WspaceMeta getMeta(String relPath, WspaceMeta.Includes includes) {

        // this can be optimized by retrieving only the props we care for.
        DavMethod pFind = null;
        try {
            if (includes.inclProps) {
                pFind = new PropFindMethod(getResourceUrl(relPath), DavConstants.PROPFIND_ALL_PROP, includes.depth);
            } else {
                pFind = new PropFindMethod(getResourceUrl(relPath), DavConstants.PROPFIND_BY_PROPERTY,
                        includes.depth);
            }

            if (!executeMethod(pFind, false)) {
                // handle error
                if (pFind.getStatusCode() != 404) {
                    System.out.println("Unable to find property:" + relPath + " -- " + pFind.getStatusText());
                }
                return null;
            }

            MultiStatus multiStatus = pFind.getResponseBodyAsMultiStatus();
            MultiStatusResponse[] resps = multiStatus.getResponses();
            if (resps == null || resps.length == 0) {
                return null;
            }
            WspaceMeta root = new WspaceMeta(getWsHome(), relPath);

            for (MultiStatusResponse res : resps) {
                if (res.getHref().equals(root.getAbsPath())) {
                    convertToWspaceMeta(root, res);
                } else {
                    addToRoot(root, res);
                }
            }
            return root;
        } catch (Exception e) {
            LOG.error(e, "Error while getting meta for:" + relPath);
        } finally {
            if (pFind != null) {
                pFind.releaseConnection();
            }
        }
        return null;
    }

    /**
     * convenience method to set one property on a resource.
     * if the property value is null, that property will be removed.
     * otherwise, the property will be either added or updated.
     * @param relPath
     * @param propName
     * @param value
     * @return
     */
    public boolean setMeta(String relPath, String propName, String value) {
        WspaceMeta meta = new WspaceMeta(null, relPath);
        meta.setProperty(propName, value);
        return setMeta(meta);
    }

    /**
     * set meta information on this dav's resource.
     * if the property value is null, that property will be removed.
     * otherwise, the property will be either added or updated.
     * @param metas
     * @return
     */
    public boolean setMeta(WspaceMeta... metas) {
        if (metas == null)
            return false;
        for (WspaceMeta meta : metas) {

            Map<String, String> props = meta.getProperties();
            if (props != null && props.size() > 0) {
                DavPropertySet newProps = new DavPropertySet();
                DavPropertyNameSet removeProps = new DavPropertyNameSet();

                for (String key : props.keySet()) {
                    String v = props.get(key);
                    if (v == null) {
                        removeProps.add(DavPropertyName.create(key, IRSA_NS));
                    } else {
                        DavProperty p = new DefaultDavProperty(key, props.get(key), IRSA_NS);
                        newProps.add(p);
                    }
                }
                try {
                    PropPatchMethod proPatch = new PropPatchMethod(getResourceUrl(meta.getRelPath()), newProps,
                            removeProps);
                    if (!executeMethod(proPatch)) {
                        // handle error
                        System.out.println("Unable to update property:" + newProps.toString() + " -- "
                                + proPatch.getStatusText());
                        return false;
                    }
                    return true;
                } catch (IOException e) {
                    LOG.error(e, "Error while setting property: " + meta);
                    e.printStackTrace();
                }

            }

        }
        return false;
    }

    //====================================================================
    //
    //====================================================================

    private WspaceMeta convertToWspaceMeta(WspaceMeta meta, MultiStatusResponse res) {
        if (meta == null) {
            meta = new WspaceMeta(getWsHome(), res.getHref().replaceFirst(getWsHome(), ""));
        }
        DavPropertySet props = res.getProperties(200);
        if (props != null) {
            for (DavProperty p : props) {
                String name = (p == null || p.getName() == null) ? null : p.getName().getName();
                if (name != null) {
                    String v = String.valueOf(p.getValue());
                    if (name.equals(DavConstants.PROPERTY_GETLASTMODIFIED)) {
                        meta.setLastModified(v);
                    } else if (name.equals(DavConstants.PROPERTY_GETCONTENTLENGTH)) {
                        try {
                            meta.setSize(Long.parseLong(v));
                        } catch (Exception e) {
                        }
                    } else if (name.equals(DavConstants.PROPERTY_GETCONTENTTYPE)) {
                        meta.setContentType(v);
                    } else if (p.getName().getNamespace().equals(IRSA_NS)) {
                        meta.setProperty(name, String.valueOf(p.getValue()));
                    }
                }
            }
        }
        return meta;
    }

    private void addToRoot(WspaceMeta root, MultiStatusResponse res) {
        WspaceMeta meta = convertToWspaceMeta(null, res);
        WspaceMeta p = root.find(meta.getParentPath());
        if (p != null) {
            p.addChild(meta);
        } else {
            root.addChild(meta);
        }
    }

    private boolean executeMethod(DavMethod method) {
        return executeMethod(method, true);
    }

    private boolean executeMethod(DavMethod method, boolean releaseConnection) {
        try {
            return partition.equals(Partition.PUBSPACE) ? HttpServices.executeMethod(method)
                    : HttpServices.executeMethod(method, "xxx", "xx", cookies);
        } finally {
            if (releaseConnection && method != null) {
                method.releaseConnection();
            }
        }

    }

    public static void main(String[] args) {
        WorkspaceManager man = ServerContext.getRequestOwner().getWsManager();
        simpleTest(man);

        //        AppProperties.setProperty("sso.server.url", "http://irsa.ipac.caltech.edu/account/");
        //        String session = JOSSOAdapter.createSession("", "");
        //        Map<String, String> cookies = new HashMap<String, String>();
        //        cookies.put(WebAuthModule.AUTH_KEY, session);
        //        WorkspaceManager man = new WorkspaceManager("<someuser>@ipac.caltech.edu", cookies);
        //        simpleTest(man);
    }

    private static void simpleTest(WorkspaceManager man) {
        File f = man.davMakeDir("123/");
        System.out.println("new directory: " + String.valueOf(f));

        WspaceMeta m = new WspaceMeta(null, "123/");
        m.setProperty("test1", "an awesome idea");
        m.setProperty("test", null);
        man.setMeta(m);

        String ufilePath = "/123/uploaded" + System.currentTimeMillis() % 1000 + ".tiff";
        man.davPut(new File("/Users/loi/dia.tiff"), ufilePath);
        man.setMeta(ufilePath, "added_by", man.userHome);

        WspaceMeta meta = man.getMeta("/", WspaceMeta.Includes.ALL_PROPS);
        System.out.println(meta.getNodesAsString());
    }
}