/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.sling.jcr.base;

import java.security.Principal;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.jcr.Credentials;
import javax.jcr.GuestCredentials;
import javax.jcr.LoginException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Value;
import javax.security.auth.Subject;

import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.base.internal.mount.ProxyRepository;
import org.apache.sling.serviceusermapping.ServiceUserMapper;
import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>AbstractSlingRepository2</code> is an abstract implementation of
 * the {@link SlingRepository} version 2.3 interface (phasing
 * {@link #loginAdministrative(String)} out in favor of
 * {@link #loginService(String, String)}) which provides default support for
 * attached repositories.
 * 
 * Implementations of the <code>SlingRepository</code> interface may wish to
 * extend this class to benefit from default implementations of most methods.
 * 
 * To be able to know the calling bundle to implement the
 * {@link #loginService(String, String)} method the bundle using the repository
 * service has to be provided in the
 * {@link #AbstractSlingRepository2(AbstractSlingRepositoryManager, Bundle)
 * constructor}.
 * 
 * The premise of this abstract class is that an instance of an implementation
 * of this abstract class is handed out to each consumer of the
 * {@code SlingRepository} service. Each instance is generally based on the same
 * {@link #getRepository() delegated repository} instance.
 *
 * @see AbstractSlingRepositoryManager
 * @since API version 2.4 (bundle version 2.3)
 */
@ProviderType
public abstract class AbstractSlingRepository2 implements SlingRepository {

    /** The logger. */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /** The repository manager. */
    private final AbstractSlingRepositoryManager manager;

    /** The bundle using this repository instance. */
    private final Bundle usingBundle;

    /**
     * Sets up this abstract SlingRepository implementation.
     *
     * @param manager The {@link AbstractSlingRepositoryManager} controlling
     *            this instance as well as the actual JCR repository instance
     *            used by this.
     * @param usingBundle The bundle using this instance. This is used by the
     *            {@link #loginService(String, String)} method, which will not
     *            be able to login if this parameter is {@code null}
     */
    protected AbstractSlingRepository2(final AbstractSlingRepositoryManager manager, final Bundle usingBundle) {
        this.manager = manager;
        this.usingBundle = usingBundle;

        if(usingBundle == null) {
            throw new IllegalArgumentException("usingBundle is null");
        }
    }

    /**
     * @return The {@link AbstractSlingRepositoryManager} controlling this
     *         instances
     */
    protected final AbstractSlingRepositoryManager getSlingRepositoryManager() {
        return this.manager;
    }

    /**
     * Returns the actual repository to which all JCR Repository interface
     * methods implemented by this class are delegated.
     *
     * @return The delegated repository.
     */
    protected final Repository getRepository() {
        return this.getSlingRepositoryManager().getRepository();
    }

    /**
     * Returns the default workspace to login to if any of the {@code login} and
     * {@code createSession} methods is called without an explicit workspace
     * name.
     * <p>
     * This method may return {@code null} in which case the actual default
     * workspace used depends on the underlying JCR Repository implementation.
     */
    @Override
    public final String getDefaultWorkspace() {
        return this.getSlingRepositoryManager().getDefaultWorkspace();
    }

    /**
     * Creates an administrative session to access the indicated workspace.
     * <p>
     * This method is called by the {@link #loginAdministrative(String)} and
     * {@link #createServiceSession(String, String)} methods.
     *
     * @param workspace The workspace to access or {@code null} to access the
     *            {@link #getDefaultWorkspace() default workspace}
     * @return An administrative session
     * @throws RepositoryException If a general error occurs during login
     * @see #createServiceSession(String, String)
     * @see #loginAdministrative(String)
     */
    protected abstract Session createAdministrativeSession(final String workspace) throws RepositoryException;


    /**
     * Creates a new service-session. This method is used by {@link #loginService(String, String)}
     * and {@link #impersonateFromService(String, Credentials, String)} to avoid
     * code duplication.
     *
     * @param usingBundle The bundle using a service session.
     * @param subServiceName The optional name of the subservice.
     * @param workspaceName The JCR workspace name or {@code null}.
     * @return A new service session or {@code null} if neither a user-name nor a
     *         principal names mapping has been defined.
     * @throws RepositoryException If an error occurs while creating the service session.
     */
    private Session createServiceSession(Bundle usingBundle, String subServiceName, String workspaceName) throws RepositoryException {
        final ServiceUserMapper serviceUserMapper = this.getSlingRepositoryManager().getServiceUserMapper();
        if (serviceUserMapper != null) {
            Session session = null;
            final Iterable<String> principalNames = serviceUserMapper.getServicePrincipalNames(usingBundle, subServiceName);
            if (principalNames != null) {
                session = createServiceSession(principalNames, workspaceName);
            }
            else
            {
                final String userName = serviceUserMapper.getServiceUserID(usingBundle, subServiceName);
                if (userName != null)
                {
                    session = createServiceSession(userName, workspaceName);
                }
            }
            if (session != null) {
                Repository repository = getRepository();
                return repository instanceof ProxyRepository ? ((ProxyRepository) repository).wrap(session) : session;
            }
        }
        return null;
    }

    /**
     * Creates a service-session for the service's {@code serviceUserName} by
     * impersonating the user from an administrative session.
     * <p>
     * The administrative session is created calling
     * {@link #createAdministrativeSession(String)
     * createAdministrativeSession(workspace)} and is logged out before this
     * method returns.
     * <p>
     * Implementations of this class may overwrite this method with a better
     * implementation, notably one which does not involve a temporary creation
     * of an administrative session.
     *
     * @param serviceUserName The name of the user to create the session for
     * @param workspace The workspace to access or {@code null} to access the
     *            {@link #getDefaultWorkspace() default workspace}
     * @return A session for the given user
     * @throws RepositoryException If a general error occurs while creating the
     *             session
     */
    protected Session createServiceSession(final String serviceUserName, final String workspace) throws RepositoryException {
        Session admin = null;
        try {
            admin = this.createAdministrativeSession(workspace);
            Session result = admin.impersonate(new SimpleCredentials(serviceUserName, new char[0]));
            Repository repository = getRepository();
            return repository instanceof ProxyRepository ? ((ProxyRepository) repository).wrap(result) : result;
        } finally {
            if (admin != null) {
                admin.logout();
            }
        }
    }

    /**
     * Creates a service-session for the service's {@code servicePrincipalNames}
     * using a pre-authenticated {@link Subject}.
     * <p>
     * Implementations of this class may overwrite this method to meet additional
     * needs wrt the the nature of the principals, the {@code Subject} or additional
     * attributes passed to the repository login.
     *
     * @param servicePrincipalNames The names of the service principals to create the session for
     * @param workspaceName The workspace to access or {@code null} to access the {@link #getDefaultWorkspace() default workspace}
     * @return A new service session
     * @throws RepositoryException If a general error occurs while creating the session.
     */
    protected Session createServiceSession(final Iterable<String> servicePrincipalNames, final String workspaceName) throws RepositoryException {
        Set<Principal> principals = new HashSet<>();
        for (final String pName : servicePrincipalNames) {
            if (pName != null && !pName.isEmpty()) {
                principals.add(new Principal() {
                    @Override
                    public String getName() {
                        return pName;
                    }
                });
            }
        };
        Subject subject = new Subject(true, principals, Collections.emptySet(), Collections.emptySet());
        try {
            return Subject.doAsPrivileged(subject, new PrivilegedExceptionAction<Session>() {
                @Override
                public Session run() throws Exception {
                    return AbstractSlingRepository2.this.getRepository().login(null, workspaceName);
                }
            }, null);
        } catch (PrivilegedActionException e) {
            throw new RepositoryException("failed to retrieve service session.", e);
        }
    }

    // login implementations (may be overwritten)

    /**
     * Same as calling {@code login(null, null)}.
     * <p>
     * This method may be overwritten.
     *
     * @return the result of calling {@link #login(Credentials, String)
     *         login(null, null)}.
     * @throws LoginException If login is not possible
     * @throws RepositoryException If another error occurrs during login
     * @see #login(Credentials, String)
     */
    @Override
    public Session login() throws LoginException, RepositoryException {
        return this.login(null, null);
    }

    /**
     * Same as calling {@code login(credentials, null)}.
     * <p>
     * This method may be overwritten.
     *
     * @param credentials The {@code Credentials} to use to login.
     * @return the result of calling {@link #login(Credentials, String)
     *         login(credentials, null)}.
     * @throws LoginException If login is not possible
     * @throws RepositoryException If another error occurrs during login
     * @see #login(Credentials, String)
     */
    @Override
    public Session login(final Credentials credentials) throws LoginException, RepositoryException {
        return this.login(credentials, null);
    }

    /**
     * Same as calling {@code login(null, workspace)}.
     * <p>
     * This method may be overwritten.
     *
     * @param workspace The workspace to access or {@code null} to access the
     *            {@link #getDefaultWorkspace() default workspace}
     * @return the result of calling {@link #login(Credentials, String)
     *         login(null, workspace)}.
     * @throws LoginException If login is not possible
     * @throws RepositoryException If another error occurrs during login
     * @see #login(Credentials, String)
     */
    @Override
    public Session login(final String workspace) throws LoginException, NoSuchWorkspaceException, RepositoryException {
        return this.login(null, workspace);
    }

    /**
     * Logs into the repository at the given {@code workspace} with the given
     * {@code credentials} and returns the session returned from
     * the repository.
     * <p>
     * This method logs in as a guest if {@code null} credentials are provided.
     * The method may be overwritten to implement a different behaviour as
     * indicated by the JCR specification for this method to use external
     * mechanisms to login instead of leveraging provided credentials.
     * <p>
     * This method may be overwritten.
     *
     * @param credentials The {@code Credentials} to use to login. If this is
     *            {@code null} JCR {@code GuestCredentials} are used to login.
     * @param workspace The workspace to access or {@code null} to access the
     *            {@link #getDefaultWorkspace() default workspace}
     * @throws LoginException If login is not possible
     * @throws NoSuchWorkspaceException if the desired workspace is not
     *             available
     * @throws RepositoryException If another error occurrs during login
     */
    @Override
    public Session login(Credentials credentials, String workspace)
            throws LoginException, NoSuchWorkspaceException, RepositoryException {

        if (credentials == null) {
            credentials = new GuestCredentials();
        }

        // check the workspace
        if (workspace == null) {
            workspace = this.getDefaultWorkspace();
        }

        try {
            logger.debug("login: Logging in to workspace '" + workspace + "'");
            final Repository repository = this.getRepository();
            if (this.getRepository() == null) {
                throw new RepositoryException("Sling Repository not ready");
            }

            final Session session = repository.login(credentials, workspace);
            return session;

        } catch (final RuntimeException re) {
            // SLING-702: Jackrabbit throws IllegalStateException if the
            // repository has already been shut down ...
            throw new RepositoryException(re.getMessage(), re);
        }
    }

    // service login

    /**
     * Actual implementation of the {@link #loginService(String, String)} method
     * taking into account the bundle calling this method.
     * 
     * This method uses the
     * {@link AbstractSlingRepositoryManager#getServiceUserMapper()
     * ServiceUserMapper} service to map the named service to a user and then
     * calls the {@link #createServiceSession(String, String)} method actually
     * create a session for that user.
     *
     * @param subServiceName An optional subService identifier (may be
     *            {@code null})
     * @param workspace The workspace to access or {@code null} to access the
     *            {@link #getDefaultWorkspace() default workspace}
     * @return A session authenticated with the service user
     * @throws LoginException if the service name cannot be derived or if
     *             logging is as the user to which the service name maps is not
     *             allowed
     * @throws RepositoryException If a general error occurs while creating the
     *             session
     */
    @Override
    public final Session loginService(final String subServiceName, final String workspace)
            throws LoginException, RepositoryException {
        Session s = createServiceSession(usingBundle, subServiceName, workspace);
        if (s != null) {
            return s;
        } else {
            throw new LoginException("Can neither derive user name nor principal names for bundle " + usingBundle + " and sub service " + subServiceName);
        }
    }

    /**
     * Default implementation of the {@link #impersonateFromService(String, Credentials, String)}
     * method taking into account the bundle calling this method.
     * 
     * This method uses the
     * {@link AbstractSlingRepositoryManager#getServiceUserMapper()
     * ServiceUserMapper} service to map the named service to a user and then
     * calls the {@link #createServiceSession(String, String)} method actually
     * create a session for that user. This service session is then impersonated
     * to the subject identified by the specified {@code credentials}.
     *
     * @param subServiceName An optional subService identifier (may be {@code null})
     * @param credentials    A valid non-null {@code Credentials} object
     * @param workspaceName  The workspace to access or {@code null} to access the
     *            {@link #getDefaultWorkspace() default workspace}
     * @return a new {@code Session} object
     * @throws LoginException If the current session does not have sufficient access to perform the operation.
     * @throws RepositoryException If another error occurs.
     * @since 2.4
     */
    @Override
    public Session impersonateFromService(final String subServiceName, final Credentials credentials, final String workspaceName)
            throws LoginException, RepositoryException {
        Session serviceSession = null;
        try {
            serviceSession = createServiceSession(usingBundle, subServiceName, workspaceName);
            if (serviceSession == null) {
                throw new LoginException("Cannot create service session for bundle " + usingBundle + " and sub service " + subServiceName);
            }
            return serviceSession.impersonate(credentials);
        } finally {
            if (serviceSession != null) {
                serviceSession.logout();
            }
        }
    }


    /**
     * Login as an administrative user. This method is deprecated and its use
     * can be completely disabled by setting {@code disableLoginAdministrative}
     * to {@code true}.
     * <p>
     * This implementation cannot be overwritten but, unless disabled, forwards
     * to the {@link #createAdministrativeSession(String)} method.
     *
     * @param workspace The workspace to access or {@code null} to access the
     *            {@link #getDefaultWorkspace() default workspace}
     * @return An administrative session
     * @throws RepositoryException If the login fails or has been disabled
     */
    @Override
    public final Session loginAdministrative(final String workspace) throws RepositoryException {
        final boolean whitelisted = getSlingRepositoryManager().allowLoginAdministrativeForBundle(usingBundle);

        if(!whitelisted) {
            final String symbolicName = usingBundle.getSymbolicName();
            logger.error("Bundle {} is NOT whitelisted to use SlingRepository.loginAdministrative", symbolicName);
            throw new LoginException("Bundle " + symbolicName +" is NOT whitelisted");
        } else if (this.getSlingRepositoryManager().isDisableLoginAdministrative()) {
            logger.error("SlingRepository.loginAdministrative is disabled. Please use SlingRepository.loginService.");
            throw new LoginException("SlingRepository.loginAdministrative is disabled.");
        }

        logger.debug("SlingRepository.loginAdministrative is deprecated. Please use SlingRepository.loginService.");
        Session result = createAdministrativeSession(workspace);
        Repository repository = getRepository();
        return repository instanceof ProxyRepository ? ((ProxyRepository) repository).wrap(result) : result;
    }

    // Remaining Repository service methods all backed by the actual
    // repository instance. They may be overwritten, but generally are not.

    @Override
    public String getDescriptor(String name) {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.getDescriptor(name);
        }

        logger.error("getDescriptor: Repository not available");
        return null;
    }

    @Override
    public String[] getDescriptorKeys() {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.getDescriptorKeys();
        }

        logger.error("getDescriptorKeys: Repository not available");
        return new String[0];
    }

    @Override
    public Value getDescriptorValue(String key) {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.getDescriptorValue(key);
        }

        logger.error("getDescriptorValue: Repository not available");
        return null;
    }

    @Override
    public Value[] getDescriptorValues(String key) {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.getDescriptorValues(key);
        }

        logger.error("getDescriptorValues: Repository not available");
        return null;
    }

    @Override
    public boolean isSingleValueDescriptor(String key) {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.isSingleValueDescriptor(key);
        }

        logger.error("isSingleValueDescriptor: Repository not available");
        return false;
    }

    @Override
    public boolean isStandardDescriptor(String key) {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.isStandardDescriptor(key);
        }

        logger.error("isStandardDescriptor: Repository not available");
        return false;
    }
}
