All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.distilledcode.tools.OakReindexInstallHook Maven / Gradle / Ivy

package net.distilledcode.tools;

import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.InstallContext;
import org.apache.jackrabbit.vault.packaging.InstallHook;
import org.apache.jackrabbit.vault.packaging.PackageException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * The OakReindexInstallHook automatically triggers a re-index of
 * Oak indexes if their definitions are modified.
 * 
* The hook works by searching any contained index definitions * in the prepare phase. It then (transiently) removes and records * the {@code reindex} and {@code reindexCount} properties of the * definition nodes. This step is necessary to avoid false positives * for definition changes. *
* Next any changes on index definitions during package installation * are tracked. *
* Finally the previously recorded properties are restored, with the * exception of modified index definitions. For them, only the * {@code reindexCount} property is restored and the {@code reindex} * property is set to {@code true}. */ public class OakReindexInstallHook implements InstallHook { private static final Logger LOG = LoggerFactory.getLogger(OakReindexInstallHook.class); public static final String PN_REINDEX = "reindex"; public static final String PN_REINDEX_COUNT = "reindexCount"; private Map reindexRecords; private final IndexDefinitionListener modificationCollector = new IndexDefinitionListener("A", "U", "D"); @Override public void execute(InstallContext context) throws PackageException { try { final Session session = context.getSession(); switch (context.getPhase()) { case PREPARE: final Set definitionPaths = collectIndexDefinitionPaths(context); reindexRecords = removeReindexProperties(session, definitionPaths); registerChangeListener(context, modificationCollector); break; case INSTALLED: reindexRecords = handleChangedIndexDefinitions( session, reindexRecords, modificationCollector.getIndexDefinitionPaths()); case END: restoreUnchangedProperties(session, reindexRecords); reindexRecords.clear(); if (session.hasPendingChanges()) { session.save(); } break; } } catch (RepositoryException e) { throw new PackageException(e); } } private static void registerChangeListener(final InstallContext context, final ProgressTrackerListener listener) { final ImportOptions options = context.getOptions(); options.setListener(CompoundProgressTrackerListener.create(options.getListener(), listener)); } private static Map handleChangedIndexDefinitions( final Session session, final Map records, final Set paths) throws RepositoryException { final Map reindexRecords = new HashMap(records); for (final String path : paths) { if (reindexRecords.containsKey(path)) { final ReindexRecord record = reindexRecords.remove(path); record.reindex = true; restoreIndexingProperties(session, path, record); LOG.info("Marked index at {} for reindexing", path); } } return reindexRecords; } private static void restoreUnchangedProperties(final Session session, final Map records) throws RepositoryException { for (final String path : records.keySet()) { final ReindexRecord record = records.get(path); restoreIndexingProperties(session, path, record); LOG.info("Restored unchanged index properties for {}", path); } } private static void restoreIndexingProperties(final Session session, final String path, final ReindexRecord record) throws RepositoryException { final Node definition = session.getNode(path); definition.setProperty(PN_REINDEX, record.reindex); if (record.reindexCount != -1) { definition.setProperty(PN_REINDEX_COUNT, record.reindexCount); } } private static Set collectIndexDefinitionPaths(InstallContext context) throws RepositoryException { final Session session = context.getSession(); final WorkspaceFilter filter = context.getPackage().getArchive().getMetaInf().getFilter(); final IndexDefinitionListener collector = new IndexDefinitionListener("A"); filter.dumpCoverage(session.getRootNode(), collector); return collector.getIndexDefinitionPaths(); } private static Map removeReindexProperties(final Session session, final Set paths) throws RepositoryException { final Map records = new HashMap(); for (final String path : paths) { final ReindexRecord record = new ReindexRecord(); final Node definition = session.getNode(path); if (definition.hasProperty(PN_REINDEX)) { final Property property = definition.getProperty(PN_REINDEX); record.reindex = property.getBoolean(); property.remove(); } if (definition.hasProperty(PN_REINDEX_COUNT)) { final Property property = definition.getProperty(PN_REINDEX_COUNT); record.reindexCount = property.getLong(); property.remove(); } records.put(path, record); } return records; } private static class ReindexRecord { boolean reindex = false; long reindexCount = -1; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy