com.wegas.core.jcr.content.ContentConnector.java Source code

Java tutorial

Introduction

Here is the source code for com.wegas.core.jcr.content.ContentConnector.java

Source

/*
 * Wegas
 * http://wegas.albasim.ch
 *
 * Copyright (c) 2013, 2014, 2015 School of Business and Engineering Vaud, Comem
 * Licensed under the MIT License
 */
package com.wegas.core.jcr.content;

import com.wegas.core.jcr.SessionHolder;
import org.apache.commons.io.IOUtils;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

import javax.jcr.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipOutputStream;

/**
 * @author Cyril Junod (cyril.junod at gmail.com)
 */
public class ContentConnector implements AutoCloseable {

    static final private org.slf4j.Logger logger = LoggerFactory.getLogger(ContentConnector.class);

    static final private String EXPORT_NODE_NAME = "exportedFiles";

    final private Session session;

    /**
     * @param bytes
     * @return string representation
     */
    public static String bytesToHumanReadable(Long bytes) {
        Integer unit = 1024;
        if (bytes < unit) {
            return bytes + "B";
        }
        Integer exponent = (int) (Math.log(bytes) / Math.log(unit));
        String prefix = ("KMGTPE").charAt(exponent - 1) + "";
        return String.format("%.1f%sB", bytes / Math.pow(unit, exponent), prefix);
    }

    /**
     * @param gameModelId
     * @throws RepositoryException
     */
    protected ContentConnector(Long gameModelId) throws RepositoryException {
        String workspace = "GM_" + gameModelId;
        this.session = SessionHolder.getSession(workspace);
        this.initializeNamespaces();

    }

    /**
     * @throws RepositoryException
     */
    protected ContentConnector() throws RepositoryException {
        this.session = SessionHolder.getSession(null);
        this.initializeNamespaces();
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected Node getNode(String absolutePath) throws RepositoryException {
        try {
            return session.getNode(absolutePath);
        } catch (PathNotFoundException ex) {
            logger.debug("Could not retrieve node ({})", ex.getMessage());
            return null;
        }
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected boolean nodeExist(String absolutePath) throws RepositoryException {
        return session.nodeExists(absolutePath);
    }

    /**
     * @param absolutePath
     * @throws RepositoryException
     */
    protected void deleteFile(String absolutePath) throws RepositoryException {
        this.getNode(absolutePath).remove();
        session.save();
    }

    /**
     * @param path
     * @return
     * @throws PathNotFoundException
     * @throws RepositoryException
     */
    protected NodeIterator listChildren(String path) throws RepositoryException {
        return session.getNode(path).getNodes(WFSConfig.WeGAS_FILE_SYSTEM_PREFIX + "*");
    }

    /*
     * Property getters and setters
     */
    private Property getProperty(String absolutePath, String propertyName) throws RepositoryException {
        Node node = this.getNode(absolutePath);
        if (node == null) {
            return null;
        } else {
            try {
                return node.getProperty(propertyName);
            } catch (PathNotFoundException ex) {
                logger.debug("Inexistant property ({}) on Node[{}]", propertyName, absolutePath);
            }
        }
        return null;
    }

    public long getLength(String absolutePath) throws RepositoryException {
        return this.getProperty(absolutePath, WFSConfig.WFS_DATA).getBinary().getSize();
    }

    protected InputStream getData(String absolutePath, long from, int len) throws RepositoryException, IOException {
        InputStream data = this.getData(absolutePath);
        byte[] bytes = new byte[len];
        data.skip(from);
        data.read(bytes, 0, len);

        return new ByteArrayInputStream(bytes);
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected InputStream getData(String absolutePath) throws RepositoryException {
        return this.getProperty(absolutePath, WFSConfig.WFS_DATA).getBinary().getStream();
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     * @throws IOException
     */
    protected byte[] getBytesData(String absolutePath) throws RepositoryException, IOException {
        return IOUtils.toByteArray(this.getData(absolutePath));
    }

    /**
     * @param absolutePath
     * @param mimeType
     * @param data
     * @return
     * @throws RepositoryException
     */
    protected Node setData(String absolutePath, String mimeType, InputStream data) throws RepositoryException {
        Node newNode = this.getNode(absolutePath);
        newNode.setProperty(WFSConfig.WFS_MIME_TYPE, mimeType);
        newNode.setProperty(WFSConfig.WFS_DATA, session.getValueFactory().createBinary(data));
        newNode.setProperty(WFSConfig.WFS_LAST_MODIFIED, Calendar.getInstance());
        this.save();
        return newNode;
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected String getMimeType(String absolutePath) throws RepositoryException {
        try {
            return this.getProperty(absolutePath, WFSConfig.WFS_MIME_TYPE).getString();
        } catch (NullPointerException ex) {
            //root
            return DirectoryDescriptor.MIME_TYPE;
        }
    }

    /**
     * @param absolutePath
     * @param mimeType
     * @throws RepositoryException
     */
    protected void setMimeType(String absolutePath, String mimeType) throws RepositoryException {
        this.getNode(absolutePath).setProperty(WFSConfig.WFS_MIME_TYPE, mimeType);
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected String getNote(String absolutePath) throws RepositoryException {
        try {
            return this.getProperty(absolutePath, WFSConfig.WFS_NOTE).getString();
        } catch (NullPointerException ex) {
            return "";
        }
    }

    /**
     * @param absolutePath
     * @param note
     * @throws RepositoryException
     */
    protected void setNote(String absolutePath, String note) throws RepositoryException {
        note = note == null ? "" : note;
        this.getNode(absolutePath).setProperty(WFSConfig.WFS_NOTE, note);
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected String getDescription(String absolutePath) throws RepositoryException {
        try {
            return this.getProperty(absolutePath, WFSConfig.WFS_DESCRIPTION).getString();
        } catch (NullPointerException ex) {
            return "";
        }
    }

    /**
     * @param absolutePath
     * @param description
     * @throws RepositoryException
     */
    protected void setDescription(String absolutePath, String description) throws RepositoryException {
        description = description == null ? "" : description;
        this.getNode(absolutePath).setProperty(WFSConfig.WFS_DESCRIPTION, description);

    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected Boolean isPrivate(String absolutePath) throws RepositoryException {
        try {
            return this.getProperty(absolutePath, WFSConfig.WFS_PRIVATE).getBoolean();
        } catch (NullPointerException ex) {
            return false;
        }
    }

    /**
     * @param absolutePath
     * @param priv
     * @throws RepositoryException
     */
    protected void setPrivate(String absolutePath, Boolean priv) throws RepositoryException {
        this.getNode(absolutePath).setProperty(WFSConfig.WFS_PRIVATE, priv);
    }

    /**
     * Check the entire path for a private property set to true
     *
     * @param absolutePath
     * @return
     */
    protected Boolean isInheritedPrivate(String absolutePath) {
        Boolean ret = false;
        Node node;
        try {
            node = this.getNode(absolutePath);
            while (!ret && !isRoot(node)) {
                try {
                    ret = node.getProperty(WFSConfig.WFS_PRIVATE).getBoolean();
                } catch (PathNotFoundException e) {
                    ret = false;
                }
                node = node.getParent();
            }
            ret = ret || (node.hasProperty(WFSConfig.WFS_PRIVATE)
                    && node.getProperty(WFSConfig.WFS_PRIVATE).getBoolean());
        } catch (RepositoryException | NullPointerException ex) {
            return false;
        }
        return ret;
    }

    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected Calendar getLastModified(String absolutePath) throws RepositoryException {
        return this.getProperty(absolutePath, WFSConfig.WFS_LAST_MODIFIED).getDate();
    }

    /*
     * Return content Bytes size
     */
    /**
     * @param absolutePath
     * @return
     * @throws RepositoryException
     */
    protected Long getBytesSize(String absolutePath) throws RepositoryException {
        return this.getProperty(absolutePath, WFSConfig.WFS_DATA).getBinary().getSize();
    }

    /**
     * Compress directory and children to ZipOutputStream. Warning: metadatas
     * are not included due to zip limitation
     *
     * @param out  a ZipOutputStream to write files to
     * @param path root path to compress
     * @throws RepositoryException
     * @throws IOException
     */
    public void zipDirectory(ZipOutputStream out, String path) throws RepositoryException, IOException {
        AbstractContentDescriptor node = DescriptorFactory.getDescriptor(path, this);
        DirectoryDescriptor root;
        if (node.isDirectory()) {
            root = (DirectoryDescriptor) node;
        } else {
            return;
        }
        List<AbstractContentDescriptor> list = root.list();

        ZipEntry entry;
        for (AbstractContentDescriptor item : list) {
            entry = item.getZipEntry();
            try {
                out.putNextEntry(entry);
            } catch (ZipException ex) {
                logger.warn("error");
            }
            if (item.isDirectory()) {
                zipDirectory(out, item.getFullPath());
            } else {
                byte[] write = ((FileDescriptor) item).getBytesData();
                out.write(write, 0, write.length);
            }
        }
        out.closeEntry();
    }

    /**
     * Jackrabbit doesn't handle workspace deletetion, falling back to remove
     * all undelying nodes
     *
     * @throws RepositoryException
     */
    public void deleteWorkspace() throws RepositoryException {
        //throw new UnsupportedOperationException("Jackrabbit: There is currently no programmatic way to delete workspaces. You can delete a workspace by manually removing the workspace directory when the repository instance is not running.");
        String name = session.getWorkspace().getName();
        Session adminSession = SessionHolder.getSession(null);
        try {
            adminSession.getWorkspace().deleteWorkspace(name);
        } catch (UnsupportedRepositoryOperationException ex) {
            logger.warn("UnsupportedRepositoryOperationException : fallback to clear workspace.");
            this.clearWorkspace();
        } finally {
            SessionHolder.closeSession(adminSession);
        }
    }

    /**
     * @param oldGameModelId
     * @throws RepositoryException
     */
    public void cloneWorkspace(Long oldGameModelId) throws RepositoryException {
        try (ContentConnector connector = ContentConnectorFactory
                .getContentConnectorFromGameModel(oldGameModelId)) {
            NodeIterator it = connector.listChildren("/");

            String path;
            while (it.hasNext()) {
                path = it.nextNode().getPath();
                session.getWorkspace().clone("GM_" + oldGameModelId, path, path, true);
            }
            PropertyIterator propertyIterator = connector.getNode("/")
                    .getProperties(WFSConfig.WeGAS_FILE_SYSTEM_PREFIX + "*");
            Property prop;
            while (propertyIterator.hasNext()) {
                prop = propertyIterator.nextProperty();
                session.getRootNode().setProperty(prop.getName(), prop.getValue());
            }
            session.save();
        }
    }

    /**
     * @throws RepositoryException
     */
    public void clearWorkspace() throws RepositoryException {
        NodeIterator it = session.getRootNode().getNodes("*");
        while (it.hasNext()) {
            Node node = it.nextNode();
            if (!(node.getName().equals("jcr:system") || node.getName().equals("rep:policy"))) {
                node.remove();
            }
        }
        PropertyIterator properties = session.getRootNode().getProperties();
        while (properties.hasNext()) {
            Property property = properties.nextProperty();
            if (!(property.getName().startsWith("jcr:") || property.getName().startsWith("rep:")
                    || property.getName().startsWith("sling:"))) {
                property.remove();
            }
        }
        this.save();
    }

    /**
     *
     */
    public void save() {
        if (session.isLive()) {
            try {
                session.save();
            } catch (RepositoryException e) {
                logger.warn(e.getMessage());
            }
        }
    }

    /**
     * @param out
     * @throws RepositoryException
     * @throws IOException
     * @throws SAXException
     */
    public void exportXML(OutputStream out) throws RepositoryException, IOException {
        final NodeIterator nodeIterator = this.listChildren("/");
        final Node exportNode = session.getRootNode().addNode(EXPORT_NODE_NAME);
        while (nodeIterator.hasNext()) {
            Node n = nodeIterator.nextNode();
            session.move(n.getPath(), exportNode.getPath() + "/" + n.getName());
        }
        session.exportSystemView(exportNode.getPath(), out, false, false);
        session.refresh(false); // Discard change.
    }

    /**
     * @param input
     * @throws RepositoryException
     * @throws IOException
     */
    public void importXML(InputStream input) throws RepositoryException, IOException {
        try {
            this.clearWorkspace(); // Remove nodes first
            final Node rootNode = session.getRootNode();
            session.save();
            session.getWorkspace().importXML("/", input, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
            final NodeIterator nodes = rootNode.getNode(EXPORT_NODE_NAME)
                    .getNodes(WFSConfig.WeGAS_FILE_SYSTEM_PREFIX + "*");
            while (nodes.hasNext()) {
                final Node node = nodes.nextNode();
                session.getWorkspace().move(node.getPath(), "/" + node.getName());
            }
            rootNode.getNode(EXPORT_NODE_NAME).remove();
        } catch (RepositoryException | IOException ex) {
            logger.error("File repository import failed", ex);
            throw ex;
        }
    }

    /**
     * Check for custom namespaces and register them if they don't exist
     *
     * @throws RepositoryException
     */
    private void initializeNamespaces() throws RepositoryException {
        for (String prefix : WFSConfig.namespaces.keySet()) {
            try {
                session.getWorkspace().getNamespaceRegistry().getURI(prefix);
            } catch (NamespaceException e) {
                session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix,
                        WFSConfig.namespaces.get(prefix));
            }
        }
    }

    private static Boolean isRoot(Node node) throws RepositoryException {
        try {
            node.getParent();
        } catch (ItemNotFoundException ex) {
            return true;
        }
        return false;
    }

    @Override
    public void close() {
        this.save();
        SessionHolder.closeSession(session);

    }
}