/*
 * 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.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Dictionary;

import javax.jcr.Credentials;
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.jcr.Workspace;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.base.util.RepositoryAccessor;
import org.apache.sling.serviceusermapping.ServiceUserMapper;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.log.LogService;
import org.slf4j.LoggerFactory;

/**
 * The <code>AbstractSlingRepository</code> is an abstract implementation of the
 * {@link SlingRepository} interface which provides default support for attached
 * repositories as well as ensuring live repository connection, reconnecting if
 * needed. Implementations of the <code>SlingRepository</code> interface may
 * wish to extend this class to benefit from a default implementation.
 * <p>
 * As of version 2.2 (bundle version 2.2.0) the registration of repository
 * services based on this abstract base class works differently. To be able to
 * know the calling bundle to implement the
 * {@link #loginService(String, String)} method the service is registered as a
 * service factory. Yet this component is registered as a non-service component
 * with Declarative Services handling its registration itself so the the
 * {@code ServiceFactory} cannot simply create instances of this class. The
 * solution is for the service factory to create a proxy to the actual component
 * object. All method calls are just routed through with the exception of the
 * {@link #loginService(String, String)} method which is routed to a new
 * internal method taking the calling bundle as an additional argument.
 * <p>
 * The changes to support this new registration mechanism are as follows:
 * <ul>
 * <li>The {@link #registerService()} method is now final.</li>
 * <li>The {@link #getServiceRegistrationInterfaces()} and
 * {@link #getServiceRegistrationProperties()} methods have been added and can
 * be overwritten by implementations of this class. The
 * {@link #registerService()} method calls these new methods to get the
 * interfaces and properties for the service registration.</li>
 * </ul>
 * Implementations of this class overwriting the {@link #registerService()}
 * method must replace this overwritten method with overwriting the new
 * {@link #getServiceRegistrationInterfaces()} and/or
 * {@link #getServiceRegistrationProperties()} methods.
 */
@Component(componentAbstract=true)
public abstract class AbstractSlingRepository
    extends AbstractNamespaceMappingRepository
    implements SlingRepository, Runnable {

    public static final String DEFAULT_ANONYMOUS_USER = "anonymous";

    public static final String DEFAULT_ANONYMOUS_PASS = "anonymous";

    public static final String DEFAULT_ADMIN_USER = "admin";

    public static final String DEFAULT_ADMIN_PASS = "admin";

    // For backwards compatibility loginAdministrative is still enabled
    // In future releases, this default may change to false.
    public static final boolean DEFAULT_LOGIN_ADMIN_ENABLED = true;

    @Property
    public static final String PROPERTY_DEFAULT_WORKSPACE = "defaultWorkspace";

    @Property(value=DEFAULT_ANONYMOUS_USER)
    public static final String PROPERTY_ANONYMOUS_USER = "anonymous.name";

    @Property(value=DEFAULT_ANONYMOUS_PASS)
    public static final String PROPERTY_ANONYMOUS_PASS = "anonymous.password";

    @Property(value=DEFAULT_ADMIN_USER)
    public static final String PROPERTY_ADMIN_USER = "admin.name";

    @Property(value=DEFAULT_ADMIN_PASS)
    public static final String PROPERTY_ADMIN_PASS = "admin.password";

    @Property(boolValue = DEFAULT_LOGIN_ADMIN_ENABLED)
    public static final String PROPERTY_LOGIN_ADMIN_ENABLED = "admin.login.enabled";

    /**
     * The default value for the number of seconds to wait between two
     * consecutive checks while the repository is active (value is 10).
     */
    public static final int DEFAULT_POLL_ACTIVE = 10;

    /**
     * The default value for the number of seconds to wait between two
     * consecutive checks while the repository is not active (value is 10).
     */
    public static final int DEFAULT_POLL_INACTIVE = 10;

    @Property(intValue=DEFAULT_POLL_ACTIVE)
    public static final String PROPERTY_POLL_ACTIVE = "poll.active";

    @Property(intValue=DEFAULT_POLL_INACTIVE)
    public static final String PROPERTY_POLL_INACTIVE = "poll.inactive";

    /** The minimum number of seconds allowed for any of the two poll times */
    public static final int MIN_POLL = 2;

    @Reference
    private LogService log;

    @Reference()
    private ServiceUserMapper serviceUserMapper;

    private ComponentContext componentContext;

    private Repository repository;

    private ServiceRegistration repositoryService;

    private String defaultWorkspace;

    private String anonUser;

    private char[] anonPass;

    private String adminUser;

    private char[] adminPass;

    private boolean disableLoginAdministrative;

    // the poll interval used while the repository is not active
    private long pollTimeInActiveSeconds;

    // the poll interval used while the repository is active
    private long pollTimeActiveSeconds;

    // whether the repository checker task should be active. this field
    // is managed by the startRepositoryPinger and stopRepositoryPinger methods
    private boolean running;

    // the background thread constantly checking the repository
    private Thread repositoryPinger;

    protected AbstractSlingRepository() {
    }

    /**
     * Returns the default workspace, which may be <code>null</code> meaning
     * to use the repository provided default workspace. Declared final to make
     * sure the SLING-256 rule is enforced.
     */
    public final String getDefaultWorkspace() {
        return defaultWorkspace;
    }

    private void setDefaultWorkspace(String defaultWorkspace) {
        // normalize the default workspace name: trim leading and trailing
        // blanks and set to null in case the trimmed name is empty
        if (defaultWorkspace != null) {
            defaultWorkspace = defaultWorkspace.trim();
            if (defaultWorkspace.length() == 0) {
                defaultWorkspace = null;
            }
        }

        log(LogService.LOG_DEBUG,
            "setDefaultWorkspace: Setting the default workspace to "
                + defaultWorkspace);
        this.defaultWorkspace = defaultWorkspace;
    }

    /**
     * Logs in as an anonymous user. This implementation simply returns the
     * result of calling {@link #login(Credentials, String)}
     */
    public Session login() throws LoginException, RepositoryException {
        return this.login(null, null);
    }

    public final Session loginAdministrative(String workspace) throws RepositoryException {
        if (this.disableLoginAdministrative) {
            log(LogService.LOG_ERROR, "SlingRepository.loginAdministrative is disabled. Please use SlingRepository.loginService.");
            throw new LoginException();
        }

        log(LogService.LOG_WARNING,
            "SlingRepository.loginAdministrative is deprecated. Please use SlingRepository.loginService.");
        return loginAdministrativeInternal(workspace);
    }

    /**
     * This method always throws {@code LoginException} because it does
     * not directly have the calling bundle at its disposition to decide
     * on the required service name.
     * <p>
     * This method is final and cannot be overwritten by extensions. See the
     * class comments for full details on how this works.
     *
     * @since 2.2 (bundle version 2.2.0)
     */
    public final Session loginService(String subServiceName, String workspace) throws LoginException,
            RepositoryException {
        log(LogService.LOG_ERROR,
            "loginService: Cannot get using Bundle because this SlingRepository service is not a ServiceFactory");
        throw new LoginException();
    }

    public Session login(Credentials credentials) throws LoginException,
            RepositoryException {
        return this.login(credentials, null);
    }

    public Session login(String workspace) throws LoginException,
            NoSuchWorkspaceException, RepositoryException {
        return this.login(null, workspace);
    }

    public Session login(Credentials credentials, String workspace)
            throws LoginException, NoSuchWorkspaceException,
            RepositoryException {

        // if already stopped, don't retrieve a session
        if (this.componentContext == null || this.getRepository() == null) {
            throw new RepositoryException("Sling Repository not ready");
        }

        if (credentials == null) {
            credentials = getAnonCredentials(this.anonUser);
        }

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

        try {
            log(LogService.LOG_DEBUG, "login: Logging in to workspace '"
                + workspace + "'");
            Session session = getRepository().login(credentials, workspace);

            // if the defualt workspace is null, acquire a session from the pool
            // and use the workspace used as the new default workspace
            if (workspace == null) {
                String defaultWorkspace = session.getWorkspace().getName();
                log(LogService.LOG_DEBUG, "login: Using " + defaultWorkspace
                    + " as the default workspace instead of 'null'");
                setDefaultWorkspace(defaultWorkspace);
            }

            return this.getNamespaceAwareSession(session);

        } catch (NoSuchWorkspaceException nswe) {
            // if the desired workspace is the default workspace, try to create
            // (but not if using the repository-supplied default workspace)
            if (workspace != null
                && workspace.equals(this.getDefaultWorkspace())
                && this.createWorkspace(workspace)) {
                return this.getRepository().login(credentials, workspace);
            }

            // otherwise (any workspace) or if workspace creation fails
            // just forward the original exception
            throw nswe;

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

    /**
     * Actual implementation of the {@link #loginService(String, String)} method
     * taking into account the bundle calling this method.
     * <p>
     * This method is final and cannot be overwritten by extensions. See the
     * class comments for full details on how this works.
     *
     * @param usingBundle The bundle requesting access
     * @param subServiceName Subservice name (may be {@code null})
     * @param workspace The workspace to access
     * @return The session authenticated with the service user
     * @throws LoginException If authentication fails or if no user is defined
     *             for the requesting service (bundle)
     * @throws RepositoryException If a general error occurrs creating the
     *             session
     *
     * @since 2.2 (bundle version 2.2.0)
     */
    final Session loginService(final Bundle usingBundle, final String subServiceName, final String workspace)
            throws LoginException, RepositoryException {
        final String userName = this.serviceUserMapper.getServiceUserID(usingBundle, subServiceName);
        final SimpleCredentials creds = new SimpleCredentials(userName, new char[0]);

        Session admin = null;
        try {
            admin = this.loginAdministrativeInternal(workspace);
            return admin.impersonate(creds);
        } finally {
            if (admin != null) {
                admin.logout();
            }
        }
    }

    /**
     * Actual (unprotected) implementation of administrative login.
     * <p>
     * This methods is internally used to administratively login.
     *
     * @param workspace The workspace to login to (or {@code null} to use the
     *            {@link #getDefaultWorkspace() default workspace}.
     * @return The administrative session
     * @throws RepositoryException if an error occurrs.
     */
    protected Session loginAdministrativeInternal(String workspace) throws RepositoryException {
        Credentials sc = getAdministrativeCredentials(this.adminUser);
        return this.login(sc, workspace);
    }

    /**
     * @param anonUser the user name of the anon user.
     * @return a Credentials implementation that represents the anon user.
     */
    protected Credentials getAnonCredentials(String anonUser) {
        // NB: this method is overridden in the Jackrabbit Service bundle to avoid using the anon password. SLING-1282
        return new SimpleCredentials(anonUser, anonPass);
    }

    /**
     * @param adminUser the name of the administrative user.
     * @return a Credentials implementation that represents the administrative user.
     */
    protected Credentials getAdministrativeCredentials(String adminUser){
        // NB: this method is overridden in the Jackrabbit Service bundle to avoid using the admin password. SLING-1282
        return new SimpleCredentials(adminUser, adminPass);
    }



    /*
     * (non-Javadoc)
     *
     * @see javax.jcr.Repository#getDescriptor(java.lang.String)
     */
    public String getDescriptor(String name) {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.getDescriptor(name);
        }

        log(LogService.LOG_ERROR, "getDescriptor: Repository not available");
        return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.jcr.Repository#getDescriptorKeys()
     */
    public String[] getDescriptorKeys() {
        Repository repo = getRepository();
        if (repo != null) {
            return repo.getDescriptorKeys();
        }

        log(LogService.LOG_ERROR, "getDescriptorKeys: Repository not available");
        return new String[0];
    }

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

        log(LogService.LOG_ERROR, "getDescriptorValue: Repository not available");
        return null;
    }

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

        log(LogService.LOG_ERROR, "getDescriptorValues: Repository not available");
        return null;
    }

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

        log(LogService.LOG_ERROR, "isSingleValueDescriptor: Repository not available");
        return false;
    }

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

        log(LogService.LOG_ERROR, "isStandardDescriptor: Repository not available");
        return false;
    }

    // ---------- logging ------------------------------------------------------

    protected void log(int level, String message) {
        this.log(level, message, null);
    }

    protected void log(int level, String message, Throwable t) {
        LogService log = this.log;
        if (log != null) {
            if (componentContext != null) {
                log.log(componentContext.getServiceReference(), level, message,
                    t);
            } else {
                log.log(level, message, t);
            }
        }
    }

    // ---------- Repository Access -------------------------------------------

    /**
     * Returns a new instance of the {@link RepositoryAccessor} class to access
     * a repository over RMI or through JNDI.
     * <p>
     * Extensions of this method may return an extension of the
     * {@link RepositoryAccessor} class if the provide extended functionality.
     */
    protected RepositoryAccessor getRepositoryAccessor() {
        return new RepositoryAccessor();
    }

    /**
     * Acquires the repository by calling the
     * {@link org.apache.sling.jcr.base.util.RepositoryAccessor#getRepositoryFromURL(String)}
     * with the value of the
     * {@link org.apache.sling.jcr.base.util.RepositoryAccessor#REPOSITORY_URL_OVERRIDE_PROPERTY}
     * framework or configuration property. If the property exists and a
     * repository can be accessed using this property, that repository is
     * returned. Otherwise <code>null</code> is returned.
     * <p>
     * Extensions of this class may overwrite this method with implementation
     * specific acquisition semantics and may call this base class method or not
     * as the implementation sees fit.
     * <p>
     * This method does not throw any <code>Throwable</code> but instead just
     * returns <code>null</code> if not repository is available. Any problems
     * trying to acquire the repository must be caught and logged as
     * appropriate.
     *
     * @return The acquired JCR <code>Repository</code> or <code>null</code>
     *         if not repository can be acquired.
     */
    protected Repository acquireRepository() {
        // if the environment provides a repository override URL, other settings
        // are ignored
        String overrideUrl = (String) componentContext.getProperties().get(
            RepositoryAccessor.REPOSITORY_URL_OVERRIDE_PROPERTY);
        if (overrideUrl == null) {
            overrideUrl = componentContext.getBundleContext().getProperty(
                RepositoryAccessor.REPOSITORY_URL_OVERRIDE_PROPERTY);
        }

        if (overrideUrl != null && overrideUrl.length() > 0) {
            log(LogService.LOG_INFO,
                "acquireRepository: Will not use embedded repository due to property "
                    + RepositoryAccessor.REPOSITORY_URL_OVERRIDE_PROPERTY + "="
                    + overrideUrl + ", acquiring repository using that URL");
            return getRepositoryAccessor().getRepositoryFromURL(overrideUrl);
        }

        log(LogService.LOG_DEBUG,
            "acquireRepository: No existing repository to access");
        return null;
    }

    /**
     * This method is called after a repository has been acquired by
     * {@link #acquireRepository()} but before the repository is registered as a
     * service.
     * <p>
     * Implementations may overwrite this method but MUST call this base class
     * implementation first.
     *
     * @param repository The JCR <code>Repository</code> to setup.
     */
    protected void setupRepository(Repository repository) {
        this.setup(componentContext.getBundleContext());
    }

    /**
     * Registers this component as an OSGi service with the types provided by
     * the {@link #getServiceRegistrationInterfaces()} method and properties
     * provided by the {@link #getServiceRegistrationProperties()} method.
     * <p>
     * As of version 2.2 (bundle version 2.2.0) this method is final and cannot
     * be overwritten because the mechanism of service registration using a
     * service factory is required to fully implement the
     * {@link #loginService(String, String)} method. See the class comments for
     * full details on how this works.
     *
     * @return The OSGi <code>ServiceRegistration</code> object representing the
     *         registered service.
     */
    protected final ServiceRegistration registerService() {
        final Dictionary<String, Object> props = getServiceRegistrationProperties();
        final String[] interfaces = getServiceRegistrationInterfaces();

        return componentContext.getBundleContext().registerService(interfaces, new ServiceFactory() {
            public Object getService(Bundle bundle, ServiceRegistration registration) {
                return SlingRepositoryProxyHandler.createProxy(interfaces, AbstractSlingRepository.this, bundle);
            }

            public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
                // nothing to do (GC does the work for us)
            }
        }, props);
    }

    /**
     * Return the service registration properties to be used to register the
     * repository service in {@link #registerService()}.
     * <p>
     * This method may be overwritten to return additional service registration
     * properties. But it is strongly recommended to always include the
     * properties returned from this method.
     *
     * @return The service registration properties to be used to register the
     *         repository service in {@link #registerService()}
     *
     * @since 2.2 (bundle version 2.2.0)
     */
    @SuppressWarnings("unchecked")
    protected Dictionary<String, Object> getServiceRegistrationProperties() {
        return componentContext.getProperties();
    }

    /**
     * Returns the service types to be used to register the repository service
     * in {@link #registerService()}. All interfaces returned must be accessible
     * to the class loader of the class of this instance.
     * <p>
     * This method may be overwritten to return additional types but the types
     * returned from this base implementation must always be included.
     *
     * @return The service types to be used to register the repository service
     *         in {@link #registerService()}
     *
     * @since 2.2 (bundle version 2.2.0)
     */
    protected String[] getServiceRegistrationInterfaces() {
        return new String[] {
            SlingRepository.class.getName(), Repository.class.getName()
        };
    }

    /**
     * Returns the repository underlying this instance or <code>null</code> if
     * no repository is currently being available.
     */
    protected Repository getRepository() {
        return repository;
    }

    /**
     * Checks that the given <code>repository</code> is still available. This
     * implementation tries to get the <code>Repository.SPEC_NAME_DESC</code>
     * descriptor from the repository and returns <code>true</code> if the
     * returned value is not <code>null</code>.
     * <p>
     * Extensions of this class may overwrite this method to implement different
     * access checks. The contract of this method must be obeyed, though in a
     * sense, the <code>true</code> must only be returned if
     * <code>repository</code> is actually usable.
     *
     * @param repository The JCR <code>Repository</code> to check for
     *            availability.
     * @return <code>true</code> if <code>repository</code> is not
     *         <code>null</code> and accessible.
     */
    protected boolean pingRepository(Repository repository) {
        if (repository != null) {
            try {
                return repository.getDescriptor(Repository.SPEC_NAME_DESC) != null;
            } catch (Throwable t) {
                log(LogService.LOG_DEBUG, "pingRepository: Repository "
                    + repository + " does not seem to be available any more", t);
            }
        }

        // fall back to unavailable
        return false;
    }

    /** Ping our current repository and check that admin login (required by Sling) works. */
    protected boolean pingAndCheck() {
        if(repository == null) {
            throw new IllegalStateException("Repository is null");
        }

        boolean result = false;

        if(pingRepository(repository)) {
            try {
                final Session s = loginAdministrativeInternal(getDefaultWorkspace());
                s.logout();
                result = true;
            } catch(RepositoryException re) {
                log.log(LogService.LOG_INFO, "pingAndCheck; loginAdministrative failed", re);
            }
        }

        return result;
    }

    /**
     * Unregisters the service represented by the
     * <code>serviceRegistration</code>.
     * <p>
     * This method may be overwritten by extensions of this class as long as it
     * is made sure, the given service registration is unregistered.
     */
    protected void unregisterService(ServiceRegistration serviceRegistration) {
        serviceRegistration.unregister();
    }

    /**
     * Performs any cleanups before the repository is actually disposed off by
     * the {@link #disposeRepository(Repository)} method.
     * <p>
     * This method is meant for cleanup tasks before the repository is actually
     * disposed off. Extensions of this class may overwrite but must call this
     * base class implementation.
     *
     * @param repository
     */
    protected void tearDown(Repository repository) {
        this.tearDown();
    }

    /**
     * Disposes off the given <code>repository</code>. This base class
     * implementation does nothing. Extensions should overwrite if any special
     * disposal operation is required.
     *
     * @param repository
     */
    protected void disposeRepository(Repository repository) {
        // nothing to do here ...
    }

    // --------- SCR integration -----------------------------------------------

    protected ComponentContext getComponentContext() {
        return this.componentContext;
    }

    /**
     * This method must be called if overwritten by implementations !!
     *
     * @throws nothing, but allow derived classes to throw any Exception
     */
    protected void activate(final ComponentContext componentContext) throws Exception {
        this.componentContext = componentContext;

        @SuppressWarnings("unchecked")
        Dictionary<String, Object> properties = componentContext.getProperties();

        setDefaultWorkspace(this.getProperty(properties,
            PROPERTY_DEFAULT_WORKSPACE, null));
        this.anonUser = this.getProperty(properties, PROPERTY_ANONYMOUS_USER,
            DEFAULT_ANONYMOUS_USER);
        this.anonPass = this.getProperty(properties, PROPERTY_ANONYMOUS_PASS,
            DEFAULT_ANONYMOUS_PASS).toCharArray();

        this.adminUser = this.getProperty(properties, PROPERTY_ADMIN_USER,
            DEFAULT_ADMIN_USER);
        this.adminPass = this.getProperty(properties, PROPERTY_ADMIN_PASS,
            DEFAULT_ADMIN_PASS).toCharArray();

        this.disableLoginAdministrative = !this.getProperty(properties, PROPERTY_LOGIN_ADMIN_ENABLED,
            DEFAULT_LOGIN_ADMIN_ENABLED);

        setPollTimeActive(getIntProperty(properties, PROPERTY_POLL_ACTIVE));
        setPollTimeInActive(getIntProperty(properties, PROPERTY_POLL_INACTIVE));

        // immediately try to start the repository while activating
        // this component instance
        try {
            if (startRepository()) {
                log(LogService.LOG_INFO, "Repository started successfully");
            } else {
                log(LogService.LOG_WARNING,
                    "Repository startup failed, will try later");
            }
        } catch (Throwable t) {
            log(LogService.LOG_WARNING,
                "activate: Unexpected problem starting repository", t);
        }

        // launch the background repository checker now
        startRepositoryPinger();
    }

    /**
     * This method must be called if overwritten by implementations !!
     *
     * @param componentContext
     */
    protected void deactivate(final ComponentContext componentContext) {
        // stop the background thread
        stopRepositoryPinger();

        // ensure the repository is really disposed off
        if (repository != null || repositoryService != null) {
            log(LogService.LOG_INFO,
                "deactivate: Repository still running, forcing shutdown");

            try {
                stopRepository();
            } catch (Throwable t) {
                log(LogService.LOG_WARNING,
                    "deactivate: Unexpected problem stopping repository", t);
            }
        }

        this.componentContext = null;
    }

    protected void bindLog(LogService log) {
        this.log = log;
    }

    protected void unbindLog(LogService log) {
        if (this.log == log) {
            this.log = null;
        }
    }

    // ---------- internal -----------------------------------------------------

    private String getProperty(Dictionary<String, Object> properties,
            String name, String defaultValue) {
        Object prop = properties.get(name);
        return (prop instanceof String) ? (String) prop : defaultValue;
    }

    private int getIntProperty(Dictionary<String, Object> properties,
            String name) {
        Object prop = properties.get(name);
        if (prop instanceof Number) {
            return ((Number) prop).intValue();
        } else if (prop != null) {
            try {
                return Integer.decode(String.valueOf(prop)).intValue();
            } catch (NumberFormatException nfe) {
                // don't really care
            }
        }

        return -1;
    }

    private boolean getProperty(Dictionary<String, Object> properties, String name, boolean defaultValue) {
        Object prop = properties.get(name);
        if (prop instanceof Boolean) {
            return ((Boolean) prop).booleanValue();
        } else if (prop instanceof String) {
            return Boolean.valueOf((String) prop);
        }

        return defaultValue;
    }

    private boolean createWorkspace(String workspace) {
        this.log(LogService.LOG_INFO, "createWorkspace: Requested workspace "
            + workspace + " does not exist, trying to create");

        Session tmpSession = null;
        try {
            Credentials sc = getAdministrativeCredentials(this.adminUser);
            tmpSession = this.getRepository().login(sc);
            Workspace defaultWs = tmpSession.getWorkspace();
            defaultWs.createWorkspace(workspace);
            return true;
        } catch (Throwable t) {
            this.log(LogService.LOG_ERROR,
                "createWorkspace: Cannot create requested workspace "
                    + workspace, t);
        } finally {
            if (tmpSession != null) {
                tmpSession.logout();
            }
        }

        // fall back to failure
        return false;
    }

    // ---------- Background operation checking repository availability --------

    private void setPollTimeActive(int seconds) {
        if (seconds < MIN_POLL) {
            seconds = DEFAULT_POLL_ACTIVE;
        }
        pollTimeActiveSeconds = seconds;
    }

    private void setPollTimeInActive(int seconds) {
        if (seconds < MIN_POLL) {
            seconds = DEFAULT_POLL_INACTIVE;
        }
        pollTimeInActiveSeconds = seconds;
    }

    private void startRepositoryPinger() {
        if (repositoryPinger == null) {
            // make sure the ping will be running
            running = true;

            // create and start the thread
            repositoryPinger = new Thread(this, "Repository Pinger");
            repositoryPinger.start();
        }
    }

    private void stopRepositoryPinger() {

        // make sure the thread is terminating
        running = false;

        // nothing to do if the thread is not running at all
        Thread rpThread = repositoryPinger;
        if (rpThread == null) {
            return;
        }

        // clear the repositoryPinger thread field
        repositoryPinger = null;

        // notify the thread for it to be able to shut down
        synchronized (rpThread) {
            rpThread.notifyAll();
        }

        // wait at most 10 seconds for the thread to terminate
        try {
            rpThread.join(10000L);
        } catch (InterruptedException ie) {
            // don't care here
        }

        // consider it an error if the thread is still running !!
        if (rpThread.isAlive()) {
            log(LogService.LOG_ERROR,
                "stopRepositoryPinger: Timed waiting for thread " + rpThread
                    + " to terminate");
        }

    }

    private boolean startRepository() {
        try {
            log(LogService.LOG_DEBUG,
                "startRepository: calling acquireRepository()");
            Repository newRepo = acquireRepository();
            if (newRepo != null) {

                // ensure we really have the repository
                log(LogService.LOG_DEBUG,
                    "startRepository: got a Repository, calling pingRepository()");
                if (pingRepository(newRepo)) {
                    repository = newRepo;

                    if(pingAndCheck()) {
                        log(LogService.LOG_DEBUG,
                            "startRepository: pingRepository() and pingAndCheck() successful, calling setupRepository()");
                        setupRepository(newRepo);

                        log(LogService.LOG_DEBUG,
                            "startRepository: calling registerService()");
                        repositoryService = registerService();

                        log(LogService.LOG_DEBUG,
                            "registerService() successful, registration="
                                + repositoryService);

                        return true;
                    }

                    // ping succeeded but pingAndCheck fail, we have to drop
                    // the repository in this situation and restart from
                    // scratch later
                    log(
                        LogService.LOG_DEBUG,
                        "pingRepository() successful but pingAndCheck() fails, calling disposeRepository()");

                    // drop reference
                    repository = null;

                } else {

                    // otherwise let go of the repository and fail startup
                    log(LogService.LOG_DEBUG,
                        "startRepository: pingRepository() failed, calling disposeRepository()");

                }

                // ping or pingAndCheck failed: dispose off repository
                disposeRepository(newRepo);
            }
        } catch (Throwable t) {
            // consider an uncaught problem an error
            log(
                LogService.LOG_ERROR,
                "startRepository: Uncaught Throwable trying to access Repository, calling stopRepository()",
                t);

            // repository might be partially started, stop anything left
            stopRepository();
        }

        return false;
    }

    private void stopRepository() {
        if (repositoryService != null) {
            try {
                log(LogService.LOG_DEBUG,
                    "Unregistering SlingRepository service, registration="
                        + repositoryService);
                unregisterService(repositoryService);
            } catch (Throwable t) {
                log(
                    LogService.LOG_INFO,
                    "stopRepository: Uncaught problem unregistering the repository service",
                    t);
            }
            repositoryService = null;
        }

        if (repository != null) {
            Repository oldRepo = repository;
            repository = null;

            try {
                tearDown(oldRepo);
            } catch (Throwable t) {
                log(
                    LogService.LOG_INFO,
                    "stopRepository: Uncaught problem tearing down the repository",
                    t);
            }

            try {
                disposeRepository(oldRepo);
            } catch (Throwable t) {
                log(
                    LogService.LOG_INFO,
                    "stopRepository: Uncaught problem disposing the repository",
                    t);
            }
        }
    }

    public void run() {
        // start polling with a small value to be faster at system startup
        // we'll increase the polling time after each try
        long pollTimeMsec = 100L;
        final long MSEC = 1000L;
        final int pollTimeFactor = 2;
        Object waitLock = repositoryPinger;

        try {

            while (running) {

                // wait first before starting to check
                synchronized (waitLock) {
                    try {
                        // no debug logging, see SLING-505
                        // log(LogService.LOG_DEBUG, "Waiting " + pollTime + " seconds before checking repository");
                        waitLock.wait(pollTimeMsec);
                    } catch (InterruptedException ie) {
                        // don't care, go ahead
                    }
                }

                long newPollTime = pollTimeMsec;
                if (running) {

                    Repository repo = repository;
                    boolean ok = false;
                    if (repo == null) {
                        // No Repository yet, try to start
                        if (startRepository()) {
                            log(LogService.LOG_INFO, "Repository started successfully");
                            ok = true;
                            newPollTime = pollTimeActiveSeconds * MSEC;
                        } else {
                            // ramp up poll time, up to the max of our configured times
                            newPollTime = Math.min(pollTimeMsec * pollTimeFactor, Math.max(pollTimeInActiveSeconds, pollTimeActiveSeconds) * MSEC);
                        }

                    } else if (pingAndCheck()) {
                        ok = true;
                        newPollTime = pollTimeActiveSeconds * MSEC;

                    } else {
                        // Repository disappeared
                        log(LogService.LOG_INFO,
                            "run: Repository not accessible anymore, unregistering service");
                        stopRepository();
                        newPollTime = pollTimeInActiveSeconds * MSEC;
                    }

                    if(newPollTime != pollTimeMsec) {
                        pollTimeMsec = newPollTime;
                        log(LogService.LOG_DEBUG,
                                "Repository Pinger interval set to " + pollTimeMsec + " msec, repository is "
                                + (ok ? "available" : "NOT available")
                                );
                    }
                }
            }

            // thread is terminating due to "running" being set to false
            log(LogService.LOG_INFO, "Repository Pinger stopping on request");

        } catch (Throwable t) {
            // try to log the cause for thread termination
            log(LogService.LOG_ERROR, "Repository Pinger caught unexpected issue", t);

        } finally {

            // whatever goes on, make sure the repository is disposed of
            // at the end of the thread....
            log(LogService.LOG_INFO, "Stopping repository on shutdown");
            stopRepository();
        }
    }

    /**
     * The <code>SlingRepositoryProxyHandler</code> class implements a proxy for all
     * service interfaces under which the {@link AbstractSlingRepository}
     * implementation is registered.
     * <p>
     * All calls a directly handed through to the object except for the
     * {@code loginService} call which is routed through
     * {@code AbstractSlingRepository.loginService(Bundle, String, String)} method
     * to influence logging in by the calling bundle.
     *
     * @since 2.2 (bundle version 2.2.0)
     */
    private static class SlingRepositoryProxyHandler implements InvocationHandler {

        // The name of the method to re-route
        private static final String LOGIN_SERVICE_NAME = "loginService";

        // The delegatee object to which all calls are routed
        private final AbstractSlingRepository delegatee;

        // The bundle using this proxy service instance
        private final Bundle usingBundle;

        /**
         * Creates a new proxy instance for the given {@code delegatee} object. The
         * proxy is handled by a new instance of this
         * {@code SlingRepositoryProxyHandler} handler.
         *
         * @param interfaceNames The list of interfaces to implement and expose in
         *            the proxy
         * @param delegatee The object to which to route all method calls
         * @param usingBundle The bundle making use of the proxy
         * @return The proxy to be used by client code or {@code null} if not all
         *         service interfaces can be loaded by the class loader of the
         *         {@code delegatee} object.
         */
        static Object createProxy(final String[] interfaceNames, final AbstractSlingRepository delegatee,
                final Bundle usingBundle) {

            // get the interface classes to create the proxy
            final ClassLoader cl = delegatee.getClass().getClassLoader();
            final Class<?>[] interfaces = new Class<?>[interfaceNames.length];
            for (int i = 0; i < interfaces.length; i++) {
                try {
                    interfaces[i] = cl.loadClass(interfaceNames[i]);
                } catch (ClassNotFoundException e) {
                    LoggerFactory.getLogger(SlingRepositoryProxyHandler.class).error(
                        "createProxy: Cannot load interface class " + interfaceNames[i], e);
                    return null;
                }
            }

            // create the proxy
            final InvocationHandler handler = new SlingRepositoryProxyHandler(delegatee, usingBundle);
            return Proxy.newProxyInstance(cl, interfaces, handler);
        }

        private SlingRepositoryProxyHandler(final AbstractSlingRepository delegatee, final Bundle usingBundle) {
            this.delegatee = delegatee;
            this.usingBundle = usingBundle;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (SlingRepositoryProxyHandler.LOGIN_SERVICE_NAME.equals(method.getName()) && args != null && args.length == 2) {
                return this.delegatee.loginService(this.usingBundle, (String) args[0], (String) args[1]);
            }

            // otherwise forward to the AbstractSlingRepository implementation
            try {
                return method.invoke(this.delegatee, args);
            } catch (InvocationTargetException ite) {
                throw ite.getTargetException();
            }
        }
    }
}
