edu.ucla.loni.server.ServerUtils.java Source code

Java tutorial

Introduction

Here is the source code for edu.ucla.loni.server.ServerUtils.java

Source

/*
 * Copyright 2012 Michael Chang, Tai-Lin Chu, Artin Menachekanian,
 *                Charles Rudolph, Eduard Sedakov, Suzanna Whiteside
 * 
 * This file is part of ServerLibraryManager.
 *
 * ServerLibraryManager is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ServerLibraryManager is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with ServerLibraryManager.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.ucla.loni.server;

import edu.ucla.loni.shared.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Timestamp;

import java.util.Date;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;

public class ServerUtils {
    //************************************************************
    // File Operations
    //************************************************************

    /**
     * Returns an unused absolute path built by combining the parameters and checking for conflicts
     * <p> Possible return values:
     * <br> root/packageName/type/name.pipe
     * <br> root/packageName/type/name_(2).pipe 
     * <br> root/packageName/type/name_(3).pipe
     * <br> etc
     */
    public static String newAbsolutePath(String root, String packageName, String type, String name) {
        String newAbsolutePath = root + File.separatorChar + packageName.replace(" ", "_") + File.separatorChar
                + type.replace(" ", "_") + File.separatorChar + name.replace(" ", "_") + ".pipe";

        File file = new File(newAbsolutePath);

        if (!file.exists()) {
            return newAbsolutePath;
        } else {
            String testPathPart = newAbsolutePath.substring(0, newAbsolutePath.lastIndexOf(".pipe"));
            String ext = ".pipe";

            for (int i = 2;; i++) {
                newAbsolutePath = testPathPart + "_(" + i + ")" + ext;
                file = new File(newAbsolutePath);

                if (!file.exists()) {
                    return newAbsolutePath;
                }
            }
        }
    }

    /**
     * Removes directory if it empty and its parent folder if that becomes empty
     * @param dir a file that is a directory
     */
    public static void removeEmptyDirectory(File dir) {
        if (dir.listFiles().length == 0) {
            dir.delete();

            File parent = dir.getParentFile();
            if (parent.listFiles().length == 0) {
                parent.delete();
            }
        }
    }

    //************************************************************
    // XML
    //************************************************************

    //------------------------------------------------------------
    // Read
    //------------------------------------------------------------

    /**
     * Parse an XML file into a Document
     */
    public static Document readXML(File pipe) throws Exception {
        SAXBuilder builder = new SAXBuilder();
        Document doc = (Document) builder.build(pipe);

        return doc;
    }

    /**
     * Parse an XML file into a Document
     */
    public static Document readXML(InputStream stream) throws Exception {
        SAXBuilder builder = new SAXBuilder();
        Document doc = (Document) builder.build(stream);

        return doc;
    }

    //------------------------------------------------------------
    // Write
    //------------------------------------------------------------

    /**
     * Write a document (XML file) to a particular absolute path
     * @throws Exception 
     */
    public static void writeXML(File file, Document doc) throws Exception {
        XMLOutputter xmlOut = new XMLOutputter();
        FileOutputStream fileOut = new FileOutputStream(file);

        xmlOut.output(doc, fileOut);

        fileOut.flush();
        fileOut.close();
    }

    //------------------------------------------------------------
    // Parse (getChildrenText and getMainElement are helpers)
    //------------------------------------------------------------

    /** 
     * Get the text value of children joined by separator
     */
    private static String getChildrenText(Element element, String childName, String separator) {
        List<Element> children = element.getChildren(childName);
        int length = children.size();

        String ret = "";
        for (int i = 0; i < length; i++) {
            Element child = children.get(i);

            String text = child.getText();
            if (text != "") {
                ret += text + separator;
            }
        }

        // Remove the last separator
        if (ret != "") {
            ret = ret.substring(0, ret.length() - separator.length());
        }

        return ret;
    }

    /** 
     * Get the main element (who has the attributes and children we care about)
     * from a document
     */
    private static Element getMainElement(Document doc) throws Exception {
        Element pipeline = doc.getRootElement();

        Element moduleGroup = pipeline.getChild("moduleGroup");
        if (moduleGroup == null) {
            throw new Exception("Pipefile does not have moduleGroup");
        } else {
            List<Element> data = moduleGroup.getChildren("dataModule");
            List<Element> module = moduleGroup.getChildren("module");

            if (data.size() == 1 && module.size() == 0) {
                return data.get(0);
            } else if (module.size() == 1 && data.size() == 0) {
                return module.get(0);
            } else {
                return moduleGroup;
            }
        }
    }

    /**
     * Parses a .pipe into a Pipefile
     */
    public static Pipefile parseXML(Document doc) {
        try {
            Pipefile pipe = new Pipefile();
            Element main = getMainElement(doc);

            String mainName = main.getName();
            if (mainName.equals("dataModule")) {
                pipe.type = "Data";
            } else if (mainName.equals("module")) {
                pipe.type = "Modules";
            } else if (mainName.equals("moduleGroup")) {
                pipe.type = "Groups";
            } else {
                throw new Exception("Pipefile has unknown type");
            }

            // General Properties
            pipe.name = main.getAttributeValue("name", "");
            pipe.packageName = main.getAttributeValue("package", "");
            pipe.description = main.getAttributeValue("description", "");
            pipe.tags = getChildrenText(main, "tag", ",");

            // Get type specific properties         
            if (pipe.type.equals("Data")) {
                Element values = main.getChild("values");
                if (values != null) {
                    pipe.values = getChildrenText(values, "value", "\n");
                }

                Element output = main.getChild("output");
                if (output != null) {
                    Element format = output.getChild("format");
                    if (format != null) {
                        pipe.formatType = format.getAttributeValue("type");
                    }
                }
            }

            if (pipe.type.equals("Modules")) {
                pipe.location = main.getAttributeValue("location", "");
            }

            if (pipe.type.equals("Modules") || pipe.type.equals("Groups")) {
                pipe.uri = main.getChildText("uri");
            }

            return pipe;
        } catch (Exception e) {
            return null;
        }
    }

    public static Pipefile parseXML(File file) {
        try {
            Document doc = readXML(file);
            Pipefile pipe = parseXML(doc);

            if (pipe != null) {
                pipe.absolutePath = file.getAbsolutePath();
            }

            return pipe;
        } catch (Exception e) {
            return null;
        }
    }

    //------------------------------------------------------------
    // Update 
    //------------------------------------------------------------

    /**
     * Updates a Document (XML file) with all the attributes from a Pipefile
     * @throws Exception 
     */
    public static Document updateXML(Document doc, Pipefile pipe) throws Exception {
        Element main = getMainElement(doc);

        // Update name (attribute)
        main.setAttribute("name", pipe.name);
        // Update package (attribute)
        main.setAttribute("package", pipe.packageName);
        // Update description (attribute)
        main.setAttribute("description", pipe.description);

        // Update the tags (children)
        main.removeChildren("tag"); // Remove all old tags
        String tags = pipe.tags;
        if (tags != null && tags.length() > 0) {
            String[] tagArray = tags.split(",");
            for (String tag : tagArray) {
                Element child = new Element("tag");
                child.setText(tag);
                main.addContent(child);
            }
        }

        if (pipe.type.equals("Data")) {
            // Update values (values child => children)
            Element valuesElement = main.getChild("values");
            if (valuesElement == null) {
                valuesElement = new Element("values");
                main.addContent(valuesElement);
            }

            valuesElement.removeChildren("value"); // Remove all old values

            String values = pipe.values;
            if (values != null && values.length() > 0) {
                String[] valueArray = values.split("\n");
                for (String value : valueArray) {
                    Element valueElement = new Element("value");
                    valueElement.setText(value);
                    valuesElement.addContent(valueElement);
                }
            }

            // Update formatType (output child => format child => attribute)
            Element output = main.getChild("output");
            if (output == null) {
                output = new Element("output");
                main.addContent(output);
            }

            Element format = output.getChild("format");
            if (format == null) {
                format = new Element("format");
                main.addContent(format);
            }

            format.setAttribute("type", pipe.formatType);
        }

        if (pipe.type.equals("Modules")) {
            // Update location (attribute)
            main.setAttribute("location", pipe.location);
        }

        if (pipe.type.equals("Modules") || pipe.type.equals("Groups")) {
            // Update uri (child)
            Element uri = main.getChild("uri");

            // If child not present, create
            if (uri == null) {
                uri = new Element("uri");
                main.addContent(uri);
            }

            uri.setText(pipe.uri);
        }

        return doc;
    }

    //************************************************************
    // Monitor File
    //************************************************************

    private static String monitorRelativePath = ".monitorfile";

    //------------------------------------------------------------
    // Get 
    //------------------------------------------------------------

    private static File getMonitorFile(Directory dir) {
        return new File(dir.absolutePath + File.separator + monitorRelativePath);
    }

    public static Timestamp getMonitorFileModified(Directory dir) {
        Timestamp ret = null;

        File monitorFile = ServerUtils.getMonitorFile(dir);
        if (monitorFile.exists()) {
            ret = new Timestamp(monitorFile.lastModified());
        }

        return ret;
    }

    //------------------------------------------------------------
    // Touch 
    //------------------------------------------------------------

    public static void touchMonitorFile(Directory dir) throws Exception {
        // Current time
        Date now = new Date();

        File monitor = getMonitorFile(dir);
        monitor.setLastModified(now.getTime());

        // Update the database
        dir.monitorModified = new Timestamp(monitor.lastModified());
        Database.updateDirectory(dir);
    }

    //************************************************************
    // Access File
    //************************************************************

    private static String accessRelativePath = ".access.xml";

    //------------------------------------------------------------
    // Get 
    //------------------------------------------------------------

    private static File getAccessFile(Directory dir) {
        return new File(dir.absolutePath + File.separator + accessRelativePath);
    }

    public static Timestamp getAccessFileModified(Directory dir) {
        Timestamp ret = null;

        File accessFile = ServerUtils.getAccessFile(dir);
        if (accessFile.exists()) {
            ret = new Timestamp(accessFile.lastModified());
        }

        return ret;
    }

    //------------------------------------------------------------
    // Read (readAccessFileGroup is a helper)
    //------------------------------------------------------------

    public static String readAccessFileGroup(Element parentEle) {
        String rs = "";
        String sep = ",";

        for (Element agent : parentEle.getChildren()) {
            String agentName = agent.getValue();
            String groupAttr = agent.getAttributeValue("group");

            boolean isGroup = groupAttr.equals("true");

            if (isGroup) {
                agentName = GroupSyntax.groupnameToAgent(agentName);
            }

            rs += agentName + sep;
        }

        if (!rs.equals("")) {
            // Get rid of final separator 
            rs = rs.substring(0, rs.length() - sep.length());
        }

        return rs;
    }

    /**
     * Reads the access file for the root directory
     * Side Effect: Updates accessFileModified in the database
     */
    public static void readAccessFile(Directory root) throws Exception {
        File accessFile = ServerUtils.getAccessFile(root);
        if (!accessFile.exists()) {
            return;
        }

        Document doc = readXML(accessFile);
        Element access = doc.getRootElement();
        Element filesRoot = access.getChild("files");
        Element groupsRoot = access.getChild("groups");

        if (filesRoot.getChildren() != null) {
            for (Element pipe : filesRoot.getChildren()) {
                String packageName = pipe.getAttributeValue("package");
                String type = pipe.getAttributeValue("type");
                String name = pipe.getAttributeValue("name");

                Pipefile thisPipe = Database.selectPipefileByHierarchy(root.dirId, packageName, type, name);

                if (thisPipe != null) {
                    thisPipe.access = readAccessFileGroup(pipe);
                    ;
                    Database.updatePipefile(thisPipe);
                }
            }
        }

        if (groupsRoot.getChildren() != null) {
            for (Element group : groupsRoot.getChildren()) {
                String name = group.getAttributeValue("name");
                String userString = readAccessFileGroup(group);

                Group thisGroup = Database.selectGroupByName(root.dirId, name);

                if (thisGroup == null) {
                    thisGroup = new Group();
                    thisGroup.name = name;
                    thisGroup.users = userString;
                    Database.insertGroup(root.dirId, thisGroup);
                } else {
                    thisGroup.users = userString;
                    Database.updateGroup(thisGroup);
                }
            }
        }

        // Update when the access file was written
        root.accessModified = new Timestamp(accessFile.lastModified());
        Database.updateDirectory(root);
    }

    //------------------------------------------------------------
    // Write (agentElement is a helper)
    //------------------------------------------------------------

    /**
     *  Creates an agent Element
     */
    public static Element agentElement(String agent) {
        agent = agent.trim();

        String value, group;

        if (GroupSyntax.isGroup(agent)) {
            value = GroupSyntax.agentToGroupname(agent);
            group = "true";
        } else {
            value = agent;
            group = "false";
        }

        return new Element("agent").addContent(value).setAttribute("group", group);
    }

    /**
     * Writes the access file for the root directory
     * Side Effect: Updates accessFileModified in the database
     */
    public static void writeAccessFile(Directory root) throws Exception {
        File accessFile = getAccessFile(root);
        if (!accessFile.exists()) {
            boolean success = accessFile.createNewFile();
            if (!success) {
                throw new Exception("Could not create access file");
            }
        }

        // <files>
        Element filesRoot = new Element("files");

        // For each pipe, add a <file> child to <files>
        Pipefile[] pipes = Database.selectPipefiles(root.dirId);

        if (pipes != null) {
            for (Pipefile p : pipes) {
                // Only add the pipefile if access is not empty
                if (!p.access.equals("")) {
                    Element file = new Element("file");
                    file.setAttribute("type", p.type);
                    file.setAttribute("name", p.name);
                    file.setAttribute("package", p.packageName);

                    // Add agents
                    String[] agents = p.access.split(",");
                    for (String agent : agents) {
                        if (!agent.equals("")) {
                            file.addContent(agentElement(agent));
                        }
                    }

                    filesRoot.addContent(file);
                }
            }
        }

        // <groups>
        Element groupsRoot = new Element("groups");

        // For each group, add a <group> child to <groups>
        Group[] groups = Database.selectGroups(root.dirId);

        if (groups != null) {
            for (Group g : groups) {
                Element group = new Element("group");
                group.setAttribute("name", g.name);

                // Add agents
                String[] agents = g.users.split(",");
                for (String agent : agents) {
                    if (!agent.equals("")) {
                        group.addContent(agentElement(agent));
                    }
                }

                groupsRoot.addContent(group);
            }
        }

        // Root Element
        Element access = new Element("access");
        access.addContent(filesRoot);
        access.addContent(groupsRoot);

        // Document
        Document doc = new Document();
        doc.addContent(access);

        // Write document
        writeXML(accessFile, doc);

        // Update when the access file was written
        root.accessModified = new Timestamp(accessFile.lastModified());
        Database.updateDirectory(root);
    }
}