org.jahia.modules.external.id.ExternalProviderInitializerServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.jahia.modules.external.id.ExternalProviderInitializerServiceImpl.java

Source

/**
 * ==========================================================================================
 * =                   JAHIA'S DUAL LICENSING - IMPORTANT INFORMATION                       =
 * ==========================================================================================
 *
 *                                 http://www.jahia.com
 *
 *     Copyright (C) 2002-2016 Jahia Solutions Group SA. All rights reserved.
 *
 *     THIS FILE IS AVAILABLE UNDER TWO DIFFERENT LICENSES:
 *     1/GPL OR 2/JSEL
 *
 *     1/ GPL
 *     ==================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE GPL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     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 3 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, see <http://www.gnu.org/licenses/>.
 *
 *
 *     2/ JSEL - Commercial and Supported Versions of the program
 *     ===================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE JSEL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     Alternatively, commercial and supported versions of the program - also known as
 *     Enterprise Distributions - must be used in accordance with the terms and conditions
 *     contained in a separate written agreement between you and Jahia Solutions Group SA.
 *
 *     If you are unsure which license is appropriate for your use,
 *     please contact the sales department at sales@jahia.com.
 */
package org.jahia.modules.external.id;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.apache.commons.lang.StringUtils;
import org.hibernate.*;
import org.hibernate.internal.util.*;
import org.jahia.modules.external.ExternalProviderInitializerService;
import org.jahia.services.cache.ehcache.EhCacheProvider;
import org.jahia.services.content.JCRStoreProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.RepositoryException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

/**
 * {@inheritDoc}
 */
public class ExternalProviderInitializerServiceImpl implements ExternalProviderInitializerService {

    private static final String ID_CACHE_NAME = "ExternalIdentifierMapping";

    private static final Logger logger = LoggerFactory.getLogger(ExternalProviderInitializerServiceImpl.class);

    private SessionFactory hibernateSessionFactory;

    private EhCacheProvider cacheProvider;
    // The ID mapping cache, where a key is a <providerKey>-<externalId-hashCode> and a value is
    // the corresponding internalId
    private Cache idCache;

    private List<String> overridableItemsForLocks;

    private List<String> overridableItemsForACLs;

    private JCRStoreProvider extensionProvider;

    @Override
    public void delete(List<String> externalIds, String providerKey, boolean includeDescendants)
            throws RepositoryException {
        if (externalIds.isEmpty()) {
            return;
        }
        StatelessSession session = null;
        try {
            List<Integer> hashes = new LinkedList<Integer>();
            for (String externalId : externalIds) {
                int hash = externalId.hashCode();
                hashes.add(hash);
            }
            session = hibernateSessionFactory.openStatelessSession();
            session.beginTransaction();

            // delete all
            session.createQuery(
                    "delete from UuidMapping where providerKey=:providerKey and externalIdHash in (:externalIds)")
                    .setString("providerKey", providerKey).setParameterList("externalIds", hashes).executeUpdate();

            if (includeDescendants) {
                // delete descendants
                Query selectStmt = session
                        .createQuery(
                                "from UuidMapping where providerKey=:providerKey and externalId like :externalId")
                        .setString("providerKey", providerKey);
                for (String externalId : externalIds) {
                    selectStmt.setString("externalId", externalId + "/%");
                    List<?> descendants = selectStmt.list();

                    for (Object mapping : descendants) {
                        UuidMapping m = (UuidMapping) mapping;
                        session.delete(m);
                        invalidateCache(m.getExternalIdHash(), providerKey);
                    }
                }
            }

            session.getTransaction().commit();

            for (String externalId : externalIds) {
                int hash = externalId.hashCode();
                invalidateCache(hash, providerKey);
            }
        } catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new RepositoryException(e);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    protected String getCacheKey(int externalIdHash, String providerKey) {
        return providerKey + "-" + externalIdHash;
    }

    @Override
    public String getExternalIdentifier(String internalId) throws RepositoryException {
        String externalId = null;
        StatelessSession session = null;
        try {
            session = getHibernateSessionFactory().openStatelessSession();
            session.beginTransaction();
            UuidMapping mapping = (UuidMapping) session.get(UuidMapping.class, internalId);
            if (mapping != null) {
                externalId = mapping.getExternalId();
            }
            session.getTransaction().commit();
        } catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new RepositoryException(e);
        } finally {
            if (session != null) {
                session.close();
            }
        }

        return externalId;
    }

    public SessionFactory getHibernateSessionFactory() {
        return hibernateSessionFactory;
    }

    public Cache getIdentifierCache() {
        return idCache;
    }

    @Override
    public String getInternalIdentifier(String externalId, String providerKey) throws RepositoryException {
        int hash = externalId.hashCode();
        String cacheKey = getCacheKey(hash, providerKey);
        String uuid = getIdentifierCache().get(cacheKey) != null
                ? (String) getIdentifierCache().get(cacheKey).getObjectValue()
                : null;
        if (uuid == null) {
            StatelessSession session = null;
            try {
                session = getHibernateSessionFactory().openStatelessSession();
                session.beginTransaction();
                List<?> list = session
                        .createQuery("from UuidMapping where providerKey=:providerKey and externalIdHash=:idHash")
                        .setString("providerKey", providerKey).setLong("idHash", hash).setReadOnly(true).list();
                if (list.size() > 0) {
                    uuid = ((UuidMapping) list.get(0)).getInternalUuid();
                    getIdentifierCache().put(new Element(cacheKey, uuid, true));
                }
                session.getTransaction().commit();
            } catch (Exception e) {
                if (session != null) {
                    session.getTransaction().rollback();
                }
                throw new RepositoryException(e);
            } finally {
                if (session != null) {
                    session.close();
                }
            }
        }

        return uuid;
    }

    @Override
    public Integer getProviderId(String providerKey) throws RepositoryException {
        ExternalProviderID providerId = null;
        SessionFactory hibernateSession = getHibernateSessionFactory();
        Session session = null;
        try {
            session = hibernateSession.openSession();
            List<?> list = session.createQuery("from ExternalProviderID where providerKey=:providerKey")
                    .setString("providerKey", providerKey).setReadOnly(true).setFlushMode(FlushMode.MANUAL).list();
            if (list.size() > 0) {
                providerId = (ExternalProviderID) list.get(0);
            } else {
                // not registered yet -> generate ID and store it
                providerId = new ExternalProviderID();
                providerId.setProviderKey(providerKey);
                try {
                    session.beginTransaction();
                    session.save(providerId);
                    session.getTransaction().commit();
                } catch (Exception e) {
                    session.getTransaction().rollback();
                    throw new RepositoryException(
                            "Issue when storing external provider ID for provider " + providerId, e);
                }
            }
        } catch (HibernateException e) {
            throw new RepositoryException("Issue when obtaining external provider ID for provider " + providerId,
                    e);
        } finally {
            if (session != null) {
                session.close();
            }
        }

        return providerId.getId();
    }

    public void invalidateCache(int externalIdHash, String providerKey) {
        getIdentifierCache().remove(getCacheKey(externalIdHash, providerKey));
    }

    public void invalidateCache(String externalId, String providerKey) {
        invalidateCache(externalId.hashCode(), providerKey);
    }

    @Override
    public String mapInternalIdentifier(String externalId, String providerKey, String providerId)
            throws RepositoryException {
        UuidMapping uuidMapping = new UuidMapping();
        uuidMapping.setExternalId(externalId);
        uuidMapping.setProviderKey(providerKey);
        uuidMapping
                .setInternalUuid(providerId + "-" + StringUtils.substringAfter(UUID.randomUUID().toString(), "-"));
        org.hibernate.Session session = null;
        Thread currentThread = Thread.currentThread();
        ClassLoader previousClassLoader = currentThread.getContextClassLoader();
        currentThread.setContextClassLoader(this.getClass().getClassLoader());
        try {
            session = getHibernateSessionFactory().openSession();
            session.beginTransaction();
            session.save(uuidMapping);
            session.getTransaction().commit();

            // cache it
            getIdentifierCache().put(new Element(getCacheKey(externalId.hashCode(), providerKey),
                    uuidMapping.getInternalUuid(), true));
        } catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new RepositoryException(
                    "Error storing mapping for external node " + externalId + " [provider: " + providerKey + "]",
                    e);
        } finally {
            if (session != null) {
                session.close();
            }
            currentThread.setContextClassLoader(previousClassLoader);
        }

        return uuidMapping.getInternalUuid();
    }

    @Override
    public void removeProvider(String providerKey) throws RepositoryException {
        SessionFactory hibernateSession = getHibernateSessionFactory();
        StatelessSession session = null;
        try {
            session = hibernateSession.openStatelessSession();
            session.beginTransaction();
            int deletedCount = session.createQuery("delete from ExternalProviderID where providerKey=:providerKey")
                    .setString("providerKey", providerKey).executeUpdate();
            if (deletedCount > 0) {
                logger.info("Deleted external provider entry for key {}", providerKey);
                deletedCount = session.createQuery("delete from UuidMapping where providerKey=:providerKey")
                        .setString("providerKey", providerKey).executeUpdate();
                logger.info("Deleted {} identifier mapping entries for external provider with key {}", deletedCount,
                        providerKey);
            } else {
                logger.info("No external provider entry found for key {}", providerKey);
            }
            session.getTransaction().commit();
        } catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new RepositoryException(
                    "Issue when removing external provider entry and identifier mappings for provider key "
                            + providerKey,
                    e);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    public void setHibernateSessionFactory(SessionFactory hibernateSession) {
        this.hibernateSessionFactory = hibernateSession;
    }

    public void setCacheProvider(EhCacheProvider cacheProvider) {
        this.cacheProvider = cacheProvider;
        idCache = cacheProvider.getCacheManager().getCache(ID_CACHE_NAME);
        if (idCache == null) {
            cacheProvider.getCacheManager().addCache(ID_CACHE_NAME);
            idCache = cacheProvider.getCacheManager().getCache(ID_CACHE_NAME);
        }
    }

    @Override
    public void updateExternalIdentifier(String oldExternalId, String newExternalId, String providerKey,
            boolean includeDescendants) throws RepositoryException {
        Session session = null;
        try {
            List<String> invalidate = new ArrayList<String>();
            session = getHibernateSessionFactory().openSession();
            session.beginTransaction();
            List<?> list = session
                    .createQuery("from UuidMapping where providerKey=:providerKey and externalIdHash=:idHash")
                    .setString("providerKey", providerKey).setLong("idHash", oldExternalId.hashCode()).list();
            if (list.size() > 0) {
                for (Object mapping : list) {
                    ((UuidMapping) mapping).setExternalId(newExternalId);
                    invalidate.add(oldExternalId);
                }
            }
            if (includeDescendants) {
                // update descendants
                List<?> descendants = session
                        .createQuery(
                                "from UuidMapping where providerKey=:providerKey and externalId like :externalId")
                        .setString("providerKey", providerKey).setString("externalId", oldExternalId + "/%").list();
                for (Object mapping : descendants) {
                    UuidMapping m = (UuidMapping) mapping;
                    m.setExternalId(newExternalId + StringUtils.substringAfter(m.getExternalId(), oldExternalId));
                    invalidate.add(m.getExternalId());
                }
            }
            session.getTransaction().commit();
            for (String id : invalidate) {
                invalidateCache(id, providerKey);
            }
        } catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new RepositoryException(e);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    public void setOverridableItemsForLocks(List<String> overridableItemsForLocks) {
        this.overridableItemsForLocks = overridableItemsForLocks;
    }

    public void setOverridableItemsForACLs(List<String> overridableItemsForACLs) {
        this.overridableItemsForACLs = overridableItemsForACLs;
    }

    public void setExtensionProvider(JCRStoreProvider extensionProvider) {
        this.extensionProvider = extensionProvider;
    }

    public List<String> getOverridableItemsForLocks() {
        return overridableItemsForLocks;
    }

    public List<String> getOverridableItemsForACLs() {
        return overridableItemsForACLs;
    }

    public JCRStoreProvider getExtensionProvider() {
        return extensionProvider;
    }
}