com.openkm.jcr.JCRUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.openkm.jcr.JCRUtils.java

Source

/**
 *  OpenKM, Open Document Management System (http://www.openkm.com)
 *  Copyright (c) 2006-2011  Paco Avila & Josep Llort
 *
 *  No bytes were intentionally harmed during the development of this application.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package com.openkm.jcr;

import java.io.File;
import java.io.IOException;
import java.security.PrivilegedAction;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.Workspace;
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;

import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.api.jsr283.security.AccessControlList;
import org.apache.jackrabbit.api.jsr283.security.AccessControlManager;
import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicyIterator;
import org.apache.jackrabbit.api.jsr283.security.Privilege;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.RepositoryCopier;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.lock.LockManager;
import org.apache.jackrabbit.core.lock.LockManagerImpl;
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.openkm.bean.Document;
import com.openkm.bean.Folder;
import com.openkm.bean.Mail;
import com.openkm.bean.StatsInfo;
import com.openkm.core.Config;
import com.openkm.core.DatabaseException;
import com.openkm.core.RepositoryException;
import com.openkm.dao.LockTokenDAO;
import com.openkm.dao.bean.LockToken;
import com.openkm.module.direct.DirectAuthModule;
import com.openkm.module.direct.DirectRepositoryModule;
import com.openkm.util.StackTraceUtils;

public class JCRUtils {
    private static Logger log = LoggerFactory.getLogger(JCRUtils.class);
    private static long activeSessions = 0;
    private static long sessionCreationCount = 0;
    private static long sessionDestroyCount = 0;

    /*   //addd by vissu on 7nov
       private static String TAXONOMY_DOCUMENTS = "/jcr:root/okm:root//element(*,okm:document)";
       private static String TEMPLATES_DOCUMENTS = "/jcr:root/okm:templates//element(*,okm:document)";
       private static String PERSONAL_DOCUMENTS = "/jcr:root/okm:personal//element(*,okm:document)";
       private static String TRASH_DOCUMENTS = "/jcr:root/okm:trash//element(*,okm:document)";
    */

    /**
     * Get parent node.
     */
    public static String getParent(String path) {
        log.debug("getParent({})", path);
        int lastSlash = path.lastIndexOf('/');
        String ret = (lastSlash > 0) ? path.substring(0, lastSlash) : "";
        log.debug("getParent: {}", ret);
        return ret;
    }

    /**
     * Get node name.
     */
    public static String getName(String path) {
        log.debug("getName({})", path);
        String ret = path.substring(path.lastIndexOf('/') + 1);
        log.debug("getName: {}", ret);
        return ret;
    }

    /**
     * Eliminate dangerous chars in node name.
     * TODO Keep on sync with uploader:com.openkm.applet.Util.escape(String)
     */
    public static String escape(String name) {
        log.debug("escape({})", name);
        String ret = name.replace('/', ' ');
        ret = ret.replace(':', ' ');
        ret = ret.replace('[', ' ');
        ret = ret.replace(']', ' ');
        ret = ret.replace('*', ' ');
        ret = ret.replace('\'', ' ');
        ret = ret.replace('"', ' ');
        ret = ret.replace('|', ' ');
        ret = ret.trim();
        log.debug("escape: {}", ret);
        return ret;
    }

    /**
     * Convert a Value array to String array and add a user id.
     */
    public static String[] usrValue2String(Value[] values, String usrId)
            throws ValueFormatException, IllegalStateException, javax.jcr.RepositoryException {
        ArrayList<String> list = new ArrayList<String>();

        for (int i = 0; i < values.length; i++) {
            // Admin and System user is not propagated across the child nodes
            if (!values[i].getString().equals(Config.SYSTEM_USER)
                    && !values[i].getString().equals(Config.ADMIN_USER)) {
                list.add(values[i].getString());
            }
        }

        if (Config.USER_ASSIGN_DOCUMENT_CREATION) {
            // No add an user twice
            if (!list.contains(usrId)) {
                list.add(usrId);
            }
        }

        return (String[]) list.toArray(new String[list.size()]);
    }

    /**
     * Convert a Value array to String array.
     */
    public static String[] rolValue2String(Value[] values)
            throws ValueFormatException, IllegalStateException, javax.jcr.RepositoryException {
        ArrayList<String> list = new ArrayList<String>();

        for (int i = 0; i < values.length; i++) {
            // Do not propagate private OpenKM roles
            if (!values[i].getString().equals(Config.DEFAULT_ADMIN_ROLE)) {
                list.add(values[i].getString());
            }
        }

        return (String[]) list.toArray(new String[list.size()]);
    }

    /**
     * 
     */
    public static String[] value2String(Value[] values)
            throws ValueFormatException, IllegalStateException, javax.jcr.RepositoryException {
        ArrayList<String> list = new ArrayList<String>();

        for (int i = 0; i < values.length; i++) {
            list.add(values[i].getString());
        }

        return (String[]) list.toArray(new String[list.size()]);
    }

    /**
     * This method discards all pending changes currently recorded in this
     * Session that apply to this Node or any of its descendants.
     *  
     * @param node The node to cancel.
     */
    public static void discardsPendingChanges(Node node) {
        try {
            // JSR-170: page 173
            // http://www.day.com/maven/jsr170/javadocs/jcr-1.0/javax/jcr/Item.html#refresh(boolean)
            if (node != null) {
                node.refresh(false);
            } else {
                log.warn("node == NULL");
            }
        } catch (javax.jcr.RepositoryException e1) {
            e1.printStackTrace();
        }
    }

    /**
     * This method discards all pending changes currently recorded in this
     * Session that apply to this Session.
     *  
     * @param node The node to cancel.
     */
    public static void discardsPendingChanges(Session session) {
        try {
            // http://www.day.com/maven/jsr170/javadocs/jcr-1.0/javax/jcr/Session.html#refresh(boolean)
            if (session != null) {
                session.refresh(false);
            } else {
                log.warn("session == NULL");
            }
        } catch (javax.jcr.RepositoryException e1) {
            e1.printStackTrace();
        }
    }

    /**
     * Make a silent logout
     * See http://jackrabbit.510166.n4.nabble.com/Lock-token-not-being-added-to-session-td2018601.html
     */
    public static void logout(Session session) {
        if (session != null && session.isLive()) {
            for (String lt : session.getLockTokens()) {
                log.debug("Remove LockToken: {}", lt);
                session.removeLockToken(lt);
            }
            session.logout();
            log.debug("#{} - {} Destroy session {} from {}", new Object[] { ++sessionDestroyCount, --activeSessions,
                    session, StackTraceUtils.whoCalledMe() });
        }
    }

    /**
     * Load lock tokens from database
     */
    public static void loadLockTokens(Session session) throws DatabaseException, javax.jcr.RepositoryException {
        List<LockToken> ltList = LockTokenDAO.findByUser(session.getUserID());

        for (Iterator<LockToken> it = ltList.iterator(); it.hasNext();) {
            LockToken lt = it.next();
            session.addLockToken(lt.getToken());
        }
    }

    /**
     * Add lock token to user data
     */
    public static void addLockToken(Session session, Node node)
            throws DatabaseException, javax.jcr.RepositoryException {
        log.debug("addLockToken({}, {})", session, node);
        LockToken lt = new LockToken();
        lt.setUser(session.getUserID());
        lt.setToken(getLockToken(node.getUUID()));
        LockTokenDAO.add(lt);
        log.debug("addLockToken: void");
    }

    /**
     * Remove lock token from user data
     */
    public static void removeLockToken(Session session, Node node)
            throws DatabaseException, javax.jcr.RepositoryException {
        log.debug("removeLockToken({}, {})", session, node);
        LockTokenDAO.remove(session.getUserID(), getLockToken(node.getUUID()));
        log.debug("removeLockToken: void");
    }

    /**
     * Obtain lock token from node
     */
    public static String getLockToken(Session session, Node node)
            throws LockException, javax.jcr.RepositoryException {
        LockManager lm = ((SessionImpl) session).getLockManager();
        Lock lock = ((LockManagerImpl) lm).getLock((NodeImpl) node);

        if (lock != null) {
            return lock.getLockToken();
        } else {
            return null;
        }
    }

    /**
     * Obtain lock token from node id
     */
    public static String getLockToken(String id) {
        StringBuffer buf = new StringBuffer();
        buf.append(id.toString());
        buf.append('-');
        buf.append(getCheckDigit(id.toString()));
        return buf.toString();
    }

    /**
     * Calculate check digit for lock token
     * 
     * @see org.apache.jackrabbit.core.lock.LockToken.getCheckDigit(String uuid)
     */
    private static char getCheckDigit(String uuid) {
        int result = 0;

        int multiplier = 36;
        for (int i = 0; i < uuid.length(); i++) {
            char c = uuid.charAt(i);
            if (c >= '0' && c <= '9') {
                int num = c - '0';
                result += multiplier * num;
                multiplier--;
            } else if (c >= 'A' && c <= 'F') {
                int num = c - 'A' + 10;
                result += multiplier * num;
                multiplier--;
            } else if (c >= 'a' && c <= 'f') {
                int num = c - 'a' + 10;
                result += multiplier * num;
                multiplier--;
            }
        }

        int rem = result % 37;
        if (rem != 0) {
            rem = 37 - rem;
        }
        if (rem >= 0 && rem <= 9) {
            return (char) ('0' + rem);
        } else if (rem >= 10 && rem <= 35) {
            return (char) ('A' + rem - 10);
        } else {
            return '+';
        }
    }

    /**
     * 
     */
    public static void grant(Session session, String path, String principal, String privilege)
            throws javax.jcr.RepositoryException {
        AccessControlManager acm = ((SessionImpl) session).getAccessControlManager();
        AccessControlPolicyIterator acpi = acm.getApplicablePolicies(path);
        AccessControlPolicy acp = acpi.nextAccessControlPolicy();
        Privilege[] privileges = new Privilege[] { acm.privilegeFromName(Privilege.JCR_ALL) };
        ((AccessControlList) acp).addAccessControlEntry(new PrincipalImpl(principal), privileges);
        session.save();
    }

    /**
     * Repository Hot-Backup 
     */
    public static File hotBackup() throws RepositoryException, IOException {
        log.debug("hotBackup()");
        String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        String backDirName = Config.CONTEXT + "_" + date;
        File backDir = new File(System.getProperty("java.io.tmpdir") + File.separator + backDirName);
        FileUtils.deleteQuietly(backDir);
        backDir.mkdir();
        boolean oldSystemReadonly = Config.SYSTEM_READONLY;

        try {
            Config.SYSTEM_READONLY = true;
            RepositoryCopier.copy((RepositoryImpl) DirectRepositoryModule.getRepository(), backDir);
        } catch (javax.jcr.RepositoryException e) {
            FileUtils.deleteQuietly(backDir);
            throw new RepositoryException(e.getMessage(), e);
        } finally {
            Config.SYSTEM_READONLY = oldSystemReadonly;
        }

        log.debug("hotBackup: {}", backDir);
        return backDir;
    }

    /**
     * Get JCR Session
     */
    public static Session getSession()
            throws javax.jcr.LoginException, javax.jcr.RepositoryException, DatabaseException {
        Object obj = null;

        try {
            InitialContext ctx = new InitialContext();
            Subject subject = (Subject) ctx.lookup("java:comp/env/security/subject");
            obj = Subject.doAs(subject, new PrivilegedAction<Object>() {
                public Object run() {
                    Session s = null;

                    try {
                        s = DirectRepositoryModule.getRepository().login();
                    } catch (javax.jcr.LoginException e) {
                        return e;
                    } catch (javax.jcr.RepositoryException e) {
                        return e;
                    }

                    return s;
                }
            });
        } catch (NamingException e) {
            throw new javax.jcr.LoginException(e.getMessage());
        }

        if (obj instanceof javax.jcr.LoginException) {
            throw (javax.jcr.LoginException) obj;
        } else if (obj instanceof javax.jcr.RepositoryException) {
            throw (javax.jcr.LoginException) obj;
        } else if (obj instanceof javax.jcr.Session) {
            Session session = (javax.jcr.Session) obj;
            log.debug("#{} - {} Create session {} from {}", new Object[] { ++sessionCreationCount, ++activeSessions,
                    session, StackTraceUtils.whoCalledMe() });
            DirectAuthModule.loadUserData(session);
            return session;
        } else {
            return null;
        }
    }

    /**
     * Get node type
     */
    public static String getNodeType(Node node) throws javax.jcr.RepositoryException {
        String ret = "unknown";

        if (node.isNodeType(Document.TYPE)) {
            ret = Document.TYPE;
        } else if (node.isNodeType(Folder.TYPE)) {
            ret = Folder.TYPE;
        } else if (node.isNodeType(Mail.TYPE)) {
            ret = Mail.TYPE;
        }

        return ret;
    }

    /**
     * Get node uuid from path
     */
    public static String getUUID(Session session, String path) throws javax.jcr.RepositoryException {
        Node rootNode = session.getRootNode();
        Node node = rootNode.getNode(path.substring(1));
        return node.getUUID();
    }

    /**
     * Get node path from uuid
     */
    public static String getPath(Session session, String uuid) throws javax.jcr.RepositoryException {
        Node node = session.getNodeByUUID(uuid);
        return node.getPath();
    }

    /**
     * Calculate user quota
     */
    public static long calculateQuota(Session session) throws javax.jcr.RepositoryException, DatabaseException {
        // "/jcr:root/okm:root//element(*, okm:document)[okm:content/@okm:author='"+session.getUserID()+"']";
        //commented below by vissu to get the whole repository size on nov6
        //String qs = "/jcr:root//element(*, okm:document)[okm:content/@okm:author='"+session.getUserID()+"']";
        Session session1 = null;
        session1 = JCRUtils.getSession();

        String qs = "/jcr:root/okm:root//element(*,okm:document)";

        Workspace workspace = session1.getWorkspace();
        QueryManager queryManager = workspace.getQueryManager();
        Query query = queryManager.createQuery(qs, Query.XPATH);
        QueryResult result = query.execute();
        long size = 0;

        for (NodeIterator nit = result.getNodes(); nit.hasNext();) {
            Node node = nit.nextNode();
            Node contentNode = node.getNode(Document.CONTENT);
            size += contentNode.getProperty(Document.SIZE).getLong();
        }

        return size;
    }
}