/*
 * 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.api.resource;

import java.util.List;
import java.util.Map;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

import org.osgi.annotation.versioning.ProviderType;

/**
 * The <code>ResourceResolverFactory</code> defines the service API to get and
 * create <code>ResourceResolver</code>s.
 * <p>
 * As soon as the resource resolver is not used anymore,
 * {@link ResourceResolver#close()} should be called.
 * <p>
 * All resource resolvers returned by the same resource resolver factory
 * must use the same search path
 *
 * @since 2.1 (Sling API Bundle 2.1.0)
 */
@ProviderType
public interface ResourceResolverFactory {

    /**
     * Name of the authentication information property providing the name of the
     * user for which the {@link #getResourceResolver(Map)} method creates
     * resource resolvers. This property may be missing in which case an
     * anonymous (unauthenticated) resource resolver is returned if possible.
     * <p>
     * The type of this property, if present, is <code>String</code>.
     */
    String USER = "user.name";

    /**
     * Name of the authentication information property providing the password of
     * the user for which to create a resource resolver. If this property is
     * missing an empty password is assumed.
     * <p>
     * The type of this property, if present, is <code>char[]</code>.
     */
    String PASSWORD = "user.password";

    /**
     * Name of the authentication information property providing the new password of
     * the user for which to create a resource resolver and change the password during login.
     * <p>
     * The type of this property, if present, is <code>String</code>.
     * @since 2.7 (Sling API Bundle 2.9.0)
     */
    String NEW_PASSWORD = "user.newpassword";

    /**
     * Name of the authentication information property causing the
     * {@link #getResourceResolver(Map)},
     * {@link #getAdministrativeResourceResolver(Map)}, and
     * {@link #getServiceResourceResolver(Map)} methods to try to impersonate
     * the created resource resolver to the requested user and return the
     * impersonated resource resolver.
     * <p>
     * If this impersonation fails the actual creation of the resource resolver
     * fails and a {@code LoginException} is thrown.
     * <p>
     * If this property is not set in the authentication info or is set to the
     * same name as the {@link #USER user.name} property this property is
     * ignored.
     * <p>
     * The type of this property, if present, is <code>String</code>.
     */
    String USER_IMPERSONATION = "user.impersonation";

    /**
     * Name of the authentication information property providing the Subservice
     * Name for the service requesting a resource resolver.
     * <p>
     * The type of this property, if present, is <code>String</code>.
     *
     * @see #getServiceResourceResolver(Map)
     * @since 2.4 (Sling API Bundle 2.5.0)
     */
    String SUBSERVICE = "sling.service.subservice";

    /**
     * Returns a new {@link ResourceResolver} instance with further
     * configuration taken from the given <code>authenticationInfo</code> map.
     * Generally this map will contain a user name and password to authenticate.
     * <p>
     * If the <code>authenticationInfo</code> map is <code>null</code> the
     * <code>ResourceResolver</code> returned will generally not be
     * authenticated and only provide minimal privileges, if any at all.
     * <p>
     * The {@link #USER_IMPERSONATION} property is obeyed but requires that the
     * actual user has permission to impersonate as the requested user. If such
     * permission is missing, a {@code LoginException} is thrown.
     *
     * @param authenticationInfo A map of further credential information which
     *            may be used by the implementation to parameterize how the
     *            resource resolver is created. This may be <code>null</code>.
     * @return A {@link ResourceResolver} according to the
     *         <code>authenticationInfo</code>.
     * @throws LoginException If an error occurs creating the new
     *             <code>ResourceResolver</code> with the provided credential
     *             data.
     */
    @Nonnull ResourceResolver getResourceResolver(Map<String, Object> authenticationInfo) throws LoginException;

    /**
     * Returns a new {@link ResourceResolver} instance with administrative
     * privileges with further configuration taken from the given
     * <code>authenticationInfo</code> map.
     * <p>
     * Note, that if the <code>authenticationInfo</code> map contains the
     * {@link #USER_IMPERSONATION} attribute the <code>ResourceResolver</code>
     * returned will only have administrative privileges if the user identified
     * by the property has administrative privileges.
     * <p>
     * <b><i>NOTE: This method is intended for use by infrastructure bundles to
     * access the repository and provide general services. This method MUST not
     * be used to handle client requests of whatever kinds. To handle client
     * requests a regular authenticated resource resolver retrieved through
     * {@link #getResourceResolver(Map)} must be used.</i></b>
     * <p>
     * This method is deprecated. Services running in the Sling system should
     * use the {@link #getServiceResourceResolver(Map)} method instead.
     * Implementations of this method should throw {@code LoginException} if
     * they don't support it.
     *
     * @param authenticationInfo A map of further credential information which
     *            may be used by the implementation to parameterize how the
     *            resource resolver is created. This may be <code>null</code>.
     * @return A {@link ResourceResolver} with administrative privileges unless
     *         the {@link #USER_IMPERSONATION} was set in the
     *         <code>authenticationInfo</code>.
     * @throws LoginException If an error occurs creating the new
     *             <code>ResourceResolver</code> with the provided credential
     *             data.
     * @deprecated as of 2.4 (bundle version 2.5.0) because of inherent security
     *             issues. Services requiring specific permissions should use
     *             the {@link #getServiceResourceResolver(Map)} instead.
     */
    @Deprecated
    @Nonnull ResourceResolver getAdministrativeResourceResolver(Map<String, Object> authenticationInfo) throws LoginException;

    /**
     * Returns a new {@link ResourceResolver} instance with privileges assigned
     * to the service provided by the calling bundle.
     * <p>
     * The provided {@code authenticationInfo} map may be used to provide
     * additional information such as the {@value #SUBSERVICE}.
     * {@link #USER} and {@link #PASSWORD} properties provided in the map are
     * ignored.
     * <p>
     * The {@link #USER_IMPERSONATION} property is obeyed but requires that the
     * actual service user has permission to impersonate as the requested user.
     * If such permission is missing, a {@code LoginException} is thrown.
     *
     * @param authenticationInfo A map of further service information which may
     *            be used by the implementation to parameterize how the resource
     *            resolver is created. This may be <code>null</code>.
     * @return A {@link ResourceResolver} with appropriate permissions to
     *         execute the service.
     * @throws LoginException If an error occurs creating the new
     *             <code>ResourceResolver</code> for the service represented by
     *             the calling bundle.
     * @since 2.4 (Sling API Bundle 2.5.0) to replace
     *        {@link #getAdministrativeResourceResolver(Map)}
     * @see <a
     *      href="http://sling.apache.org/documentation/the-sling-engine/service-authentication.html">Service
     *      Authentication</a>
     */
    @Nonnull ResourceResolver getServiceResourceResolver(Map<String, Object> authenticationInfo) throws LoginException;

    /**
     * Returns the {@link ResourceResolver} for the current thread.
     * <p>
     * Each resource resolver created by {@link #getResourceResolver(Map)} is associated with
     * the thread of its creation time. From within this thread, this method returns
     * the last non-closed resource resolver. When a resource resolver is closed, the
     * association is removed.
     * <p>
     * This will never return a resource resolver being created via {@link #getAdministrativeResourceResolver(Map)}
     * nor via {@link #getServiceResourceResolver(Map)}.
     *
     * @return A {@link ResourceResolver} created from the current thread or <code>null</code>.
     *
     * @since 2.6 (Sling API Bundle 2.8.0)
     */
    @CheckForNull ResourceResolver getThreadResourceResolver();

    /**
     * Returns the search path used by the resource resolvers to search for
     * resources by relative path. If no search path is set an empty list
     * is returned.
     * <p>
     * Each entry in the list is an absolute path terminated with a slash
     * character. Thus to create an absolute path from a search path entry and a
     * relative path, the search path entry and relative path may just be
     * concatenated.
     *
     * @return An immutable list containing the search path
     * @since 2.11 (Sling API Bundle 2.18.0)
     */
    @Nonnull List<String> getSearchPath();
}
