org.onehippo.forge.solr.indexer.task.JcrUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.onehippo.forge.solr.indexer.task.JcrUtils.java

Source

/*
 *  Copyright 2012 Hippo.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.onehippo.forge.solr.indexer.task;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeType;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * JCR utilities
 * @author Mickal Tricot
 * @version $Id: JcrUtils.java 129978 2012-02-06 22:08:51Z mtricot $
 */
public final class JcrUtils {

    /** Logger */
    private static final Logger log = LoggerFactory.getLogger(JcrUtils.class);

    /** Node types cache (including super types) */
    private static final Map<NodeType, Collection<String>> NODE_TYPES = new HashMap<NodeType, Collection<String>>();

    /** Path to availability */
    private static final String PATH_AVAILABILITY = "hippo:availability";

    /** Path separator */
    private static final String PATH_SEPARATOR = "/";

    /** Path to UUID */
    private static final String PATH_UUID = "jcr:uuid";

    /**
     * Close session quietly (does not throw exception)
     * @param session Session
     */
    public static void closeQuietly(Session session) {
        if (session != null) {
            try {
                session.logout();
            } catch (Exception e) { // NOSONAR
                //
            }
        }
    }

    /**
     * Get node types (including super types)
     * @param node Node
     * @return Node types (including super types)
     */
    private static Collection<String> getNodeTypes(Node node) {
        try {
            Collection<String> nodeTypes = NODE_TYPES.get(node.getPrimaryNodeType());
            if (nodeTypes == null) {
                nodeTypes = new HashSet<String>();
                nodeTypes.add(node.getPrimaryNodeType().getName());
                for (NodeType superType : node.getPrimaryNodeType().getSupertypes()) {
                    nodeTypes.add(superType.getName());
                }
                NODE_TYPES.put(node.getPrimaryNodeType(), Collections.unmodifiableCollection(nodeTypes));
            }
            return nodeTypes;
        } catch (RepositoryException e) {
            log.error("Failed to retrieve node (super) types at " + getPath(node), e);
            return Collections.emptySet();
        }
    }

    /**
     * Returns the JCR item path, for logging purposes (silent, exception caught)
     * @param item JCR item
     * @return Path
     */
    public static String getPath(Item item) {
        try {
            return item.getPath();
        } catch (RepositoryException e) {
            return null;
        }
    }

    /**
     * Get JCR property (nested property if path contains '/')
     * @param node JCR node
     * @param propertyPath JCR property path
     * @return JCR property (nullable)
     */
    public static Property getProperty(Node node, String propertyPath) {
        String propertyPathStripped = StringUtils.strip(propertyPath, PATH_SEPARATOR);
        try {
            if (StringUtils.contains(propertyPathStripped, PATH_SEPARATOR)) {
                String nodePath = StringUtils.split(propertyPathStripped, PATH_SEPARATOR)[0];
                if (node.hasNode(nodePath)) {
                    return getProperty(node.getNode(nodePath),
                            StringUtils.removeStart(propertyPathStripped, nodePath));
                }
            } else if (node.hasProperty(propertyPathStripped)) {
                return node.getProperty(propertyPathStripped);
            }
        } catch (RepositoryException e) {
            log.error("Failed to retrieve property " + propertyPath + " for node at " + getPath(node), e);
        }
        return null;
    }

    /**
     * Get UUID for a node (handle UUID if the node is a document)
     * @param node Node
     * @return UUID
     */
    public static String getUUID(Node node) {
        if (node == null) {
            return null;
        }
        String uuid = null;
        try {
            // The UUID of a document is changing over the changes, so we try to use the handle UUID instead
            Node parent = node.getParent();
            uuid = isHandle(parent) ? parent.getIdentifier() : node.getIdentifier();
        } catch (RepositoryException e) {
            log.error("Failed to retrieve the handle UUID for node " + getPath(node), e);
        }
        if (uuid == null) {
            try {
                uuid = node.getIdentifier();
            } catch (RepositoryException e) {
                log.error("Failed to retrieve the handle UUID for node " + getPath(node), e);
            }
        }
        return uuid;
    }

    /**
     * Check if a node is a folder
     * @param node Node
     * @return TRUE if it is a folder
     */
    public static boolean isFolder(Node node) {
        return node != null && getNodeTypes(node).contains("hippostd:folder");
    }

    /**
     * Check if a node is a handle
     * @param node Node
     * @return TRUE if it is a handle
     */
    public static boolean isHandle(Node node) {
        return node != null && getNodeTypes(node).contains("hippo:handle");
    }

    /**
     * Check if a node is live
     * @param node Node
     * @return TRUE if the node is live
     */
    public static boolean isLive(Node node) {
        boolean isLive = false;
        try {
            if (!node.hasProperty(PATH_AVAILABILITY)) {
                return true;
            }
            Value[] values = node.getProperty(PATH_AVAILABILITY).getValues();
            int i = 0;
            while (!isLive && i < values.length) {
                isLive = "live".equals(values[i].getString());
                ++i;
            }
        } catch (RepositoryException e) {
            log.error("Failed to retrieve property " + PATH_AVAILABILITY + " for node at " + getPath(node), e);
        }
        return isLive;
    }

    /**
     * Check if a node is of a certain type
     * @param node Node
     * @param types Types
     * @return TRUE if the node matches with one of the types
     */
    public static boolean isOfType(Node node, Collection<String> types) {
        if (node == null || types == null || types.isEmpty()) {
            return false;
        }
        Collection<String> intersect = new ArrayList<String>(types);
        intersect.retainAll(getNodeTypes(node));
        return !intersect.isEmpty();
    }

    /**
     * Read property value
     * @param node Node
     * @param propertyPath Property path
     * @return Property value (array if multiple property)
     */
    public static Object readPropertyValue(Node node, String propertyPath) {
        if (node == null || StringUtils.isBlank(propertyPath)) {
            return null;
        }
        Object value = null;
        if (PATH_UUID.equals(propertyPath)) {
            value = getUUID(node);
        }
        if (value == null) {
            Property property = getProperty(node, propertyPath);
            if (property != null) {
                try {
                    if (property.isMultiple()) {
                        Collection<Object> multiPropertyValue = new ArrayList<Object>();
                        for (Value propertyValue : property.getValues()) {
                            Object o = toObject(propertyValue);
                            if (o != null) {
                                multiPropertyValue.add(o);
                            }
                        }
                        value = multiPropertyValue.isEmpty() ? null : multiPropertyValue;
                    } else {
                        value = toObject(property.getValue());
                    }
                } catch (RepositoryException e) {
                    log.error("Failed to retrieve property " + getPath(property), e);
                }
            }
        }
        return value;
    }

    /**
     * Convert a JCR value into a Java object
     * @param value JCR value
     * @return Java object (nullable)
     */
    private static Object toObject(Value value) {
        if (value == null) {
            return null;
        }
        Object object = null;
        try {
            switch (value.getType()) {
            case PropertyType.BOOLEAN:
                object = value.getBoolean();
                break;
            case PropertyType.DATE:
                object = value.getDate();
                break;
            case PropertyType.DECIMAL:
                object = value.getDecimal();
                break;
            case PropertyType.DOUBLE:
                object = value.getDouble();
                break;
            case PropertyType.LONG:
                object = value.getLong();
                break;
            case PropertyType.NAME:
                object = value.getString();
                break;
            case PropertyType.STRING:
                object = StringUtils.trimToNull(value.getString());
                break;
            default:
                log.warn("Unhandled JCR type {}", PropertyType.nameFromValue(value.getType()));
            }
        } catch (RepositoryException e) {
            log.warn("Error while reading property value: " + value, e);
        }
        return object;
    }

    /** Constructor (prevents instantiation) */
    private JcrUtils() {
    }
}