Groovy BinariesInfoScript

The BinariesInfoScript

The following updater script logs information about binaries, i.e. assets and/or images, that are selected by the given XPath query.

Description

Find assets and/or images based on size limits and output their primary type, mime type, size and path, plus the number of visited binaries and the number of binaries within the given limits.

XPath query

Set a query for binaries, i.e. JCR hippo:resource nodes.

E.g. all images: 

content/gallery//element(*,hippo:resource)

E.g. all assets: 

content/assets//element(*,hippo:resource)

E.g. all MS Excel assets: 

content/assets//element(*,hippo:resource)[@jcr:mimeType="application/vnd.ms-excel"]

E.g. all pdf resources embedded in documents: 

content/documents//element(*, hippo:resource)[@jcr:mimeType='application/pdf']

Parameters

{"lowerLimit": "1k", "upperLimit": "10M", "verbose":  "true"}

lowerLimit/upperLimit: lower and upper limits of the size of the binaries to find (optional, inclusive).
                       Postfixes k, M and G are supported.
verbose: true (default): outputs the list of binaries within the limits (showing primaryType, mimeType, size, path) and the summary
         false:          outputs only the summary: number of visited binaries and number of binaries within the limits

Script

package org.hippoecm.frontend.plugins.cms.admin.updater

import org.onehippo.repository.update.BaseNodeUpdateVisitor

import javax.jcr.Node
import javax.jcr.RepositoryException
import javax.jcr.Session

/**
 * Find binaries (assets or images) in the repository and output their type, mime type, path and size if their size lies
 * between the configured limits.
 *
 *  XPath query (typically): content/assets//element(*,hippo:resource)
 *
 *  Parameters: {"lowerLimit": "1k", "upperLimit": "10M", "verbose":  "true"}
 *   lowerLimit/upperLimit:   lower and upper limits of the size of the binaries to find (optional, inclusive).
 *                            Postfixes k, M and G are supported.
 *   verbose: true (default): outputs the list of binaries within the limits (showing primaryType, mimeType, size, path) 
 *                            and the summary
 *            false:          outputs only the summary: number of visited binaries and number of binaries within the limits
 */
class BinariesInfoScript extends BaseNodeUpdateVisitor {

    Boolean verbose = null
    String configuredLowerLimit = null
    String configuredUpperLimit = null
    Long lowerLimit = null
    Long upperLimit = null

    List<BinariesInfo> binariesWithinLimits = new ArrayList<BinariesInfo>()
    int totalVisitedNodes = 0

    void initialize(Session session) throws RepositoryException {
        verbose = !("false" == parametersMap.get("verbose"))
        configuredLowerLimit = parametersMap.get("lowerLimit")
        configuredUpperLimit = parametersMap.get("upperLimit")
        lowerLimit = getSize(configuredLowerLimit, 0L)
        upperLimit = getSize(configuredUpperLimit, Long.MAX_VALUE)

        log.info "BinariesInfoScript initialized with parameters lowerLimit=${configuredLowerLimit}, " +
                "upperLimit=${configuredUpperLimit}, verbose=${verbose}."
    }

    boolean logSkippedNodePaths() {
        return false // don't log skipped node paths
    }

    boolean skipCheckoutNodes() {
        return false // return true for readonly visitors and/or updates unrelated to versioned content
    }

    Node firstNode(final Session session) throws RepositoryException {
        return null // implement when using custom node selection/navigation
    }

    Node nextNode() throws RepositoryException {
        return null // implement when using custom node selection/navigation
    }

    boolean doUpdate(Node node) {
        totalVisitedNodes++
        log.debug "BinariesInfoScript visiting node ${node.path} of type ${node.primaryNodeType.name}"

        if (node.hasProperty("jcr:data")) {
            long size = node.getProperty("jcr:data").getLength()
            if ((size >= lowerLimit) && (size <= upperLimit)) {

                final String primaryType =  node.getProperty("jcr:primaryType").getString();
                final String mimeType =  node.hasProperty("jcr:mimeType") ? node.getProperty("jcr:mimeType").getString() : "none"

                binariesWithinLimits.add(new BinariesInfo(primaryType, mimeType, size, node.getPath()))
            }
            return true
        }

        log.warn "Unexpectedly, node ${node.getPath()} does not have property jcr:data"
        return false
    }

    boolean undoUpdate(Node node) {
        throw new UnsupportedOperationException('Updater does not implement undoUpdate method')
    }

    void destroy() {
        logOutput()
    }

    void logOutput() {

        StringBuilder sb = new StringBuilder()
        if (verbose && binariesWithinLimits.size() > 0) {
            sb.append("Detailed binaries information (primaryType, mimeType, size, path):\n")
            for (BinariesInfo info : binariesWithinLimits) {
                sb.append("  ").append(info.getPrimaryType()).append(", ").append(info.getMimeType()).append(", ")
                sb.append(info.getSize()).append(", ").append(info.getPath()).append("\n")
            }
        }

        sb.append("Summary of binaries information:\n")
        sb.append("  Total of visited binaries is ").append(totalVisitedNodes).append(".\n")
        sb.append("  Found ").append(binariesWithinLimits.size()).append(" binaries")
        sb.append(" larger than ").append(lowerLimit).append(" bytes")
        if ((configuredLowerLimit != null) && (configuredLowerLimit.length() > 0)) {
            sb.append(" (").append(configuredLowerLimit).append(")")
        }
        if (upperLimit != Long.MAX_VALUE) {
            sb.append(" and smaller than ").append(upperLimit).append(" bytes (").append(configuredUpperLimit).append(")")
        }
        sb.append(".\n")

        log.info(sb.toString())
    }


    Long getSize(final String configuredSize, final Long defaultValue) {

        if ((configuredSize == null) || configuredSize.length() == 0) {
            return defaultValue
        }

        try {
            if (configuredSize.endsWith("G")) {
                return Long.parseLong(configuredSize.substring(0, configuredSize.length()-1)) * 1024 * 1024 * 1024;
            }
            else if (configuredSize.endsWith("M")) {
                return Long.parseLong(configuredSize.substring(0, configuredSize.length()-1)) * 1024 * 1024
            }
            else if (configuredSize.endsWith("k")) {
                return Long.parseLong(configuredSize.substring(0, configuredSize.length()-1)) * 1024
            }
            else {
                return Long.parseLong(configuredSize)
            }
        }
        catch (NumberFormatException nfe) {
            log.error("Configured size {} cannot be parsed into a long. Defaulting to {}", configuredSize, defaultValue);
            return defaultValue
        }
    }

    /**
     * Information about a found binary.
     */
    class BinariesInfo {
        private final String primaryType
        private final String mimeType
        private final long size
        private final String path

        BinariesInfo(final String primaryType, final String mimeType, final long size, final String path) {
            this.primaryType = primaryType
            this.mimeType = mimeType
            this.size = size
            this.path = path
        }

        String getPrimaryType() {
            return primaryType
        }

        String getMimeType() {
            return mimeType
        }

        long getSize() {
            return size
        }

        String getPath() {
            return path
        }
    }
}
Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?