/*
 * 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.classloader.internal;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;

import org.apache.sling.commons.classloader.ClassLoaderWriter;
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ServiceScope;
import org.osgi.service.component.propertytypes.ServiceDescription;
import org.osgi.service.component.propertytypes.ServiceVendor;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>DynamicClassLoaderProviderImpl</code> provides
 * a class loader which loads classes from configured paths
 * in the repository.
 * It implements the {@link ClassLoaderWriter} interface
 * for clients to use for writing and reading such
 * classes and resources.
 */
@Component(
        name = "org.apache.sling.jcr.classloader.internal.DynamicClassLoaderProviderImpl",
        service = ClassLoaderWriter.class,
        scope = ServiceScope.BUNDLE)
@ServiceDescription("Repository based classloader writer")
@ServiceVendor("The Apache Software Foundation")
public class ClassLoaderWriterImpl implements ClassLoaderWriter {

    /** Logger */
    private final Logger logger = LoggerFactory.getLogger(ClassLoaderWriterImpl.class);

    private static final String CLASS_PATH_DEFAULT = "/var/classes";

    @ObjectClassDefinition(name="%loader.name", description="%loader.description")
    public @interface Config {

        @AttributeDefinition
        String classpath() default CLASS_PATH_DEFAULT;

        @AttributeDefinition
        boolean appendId() default true;

        @AttributeDefinition
        String owner() default OWNER_DEFAULT;
    }

    /** Node type for packages/folders. */
    private static final String NT_FOLDER = "nt:folder";

    /** Default class loader owner. */
    private static final String OWNER_DEFAULT = "admin";

    @Reference
    private SlingSettingsService settings;

    /** The owner of the class loader / JCR user. */
    private String classLoaderOwner;

    /** The configured class path. */
    private String classPath;

    @Reference
    private SlingRepository repository;

    @Reference(policy= ReferencePolicy.DYNAMIC, cardinality= ReferenceCardinality.OPTIONAL)
    private volatile MimeTypeService mimeTypeService;

    @Reference(
            service = DynamicClassLoaderManager.class,
            bind = "bindDynamicClassLoaderManager",
            unbind = "unbindDynamicClassLoaderManager")
    private volatile ServiceReference dynamicClassLoaderManager;

    /** The bundle asking for this service instance */
    private Bundle callerBundle;

    /** Cached repository class loader. */
    private volatile RepositoryClassLoader repositoryClassLoader;

    /**
     * Activate this component.
     * @param componentContext The component context
     * @param config The configuration properties
     */
    @Activate
    protected void activate(final ComponentContext componentContext, Config config) {
        this.classPath = config.classpath();
        if ( this.classPath.endsWith("/") ) {
            this.classPath = this.classPath.substring(0, this.classPath.length() - 1);
        }
        if ( config.appendId()) {
            this.classPath = this.classPath + '/' + this.settings.getSlingId();
        }

        this.classLoaderOwner = config.owner();

        this.callerBundle = componentContext.getUsingBundle();
    }

    /**
     * Deactivate this component.
     */
    @Deactivate
    protected synchronized void deactivate() {
        this.destroyRepositoryClassLoader();
        this.callerBundle = null;
    }

    /**
     * Called to handle binding the DynamicClassLoaderManager service
     * reference
     */
    @SuppressWarnings("unused")
    private void bindDynamicClassLoaderManager(final ServiceReference ref) {
        this.dynamicClassLoaderManager = ref;
    }

    /**
     * Called to handle unbinding of the DynamicClassLoaderManager service
     * reference
     */
    @SuppressWarnings("unused")
    private void unbindDynamicClassLoaderManager(final ServiceReference ref) {
        if (this.dynamicClassLoaderManager == ref) {
            this.dynamicClassLoaderManager = null;
        }
    }

    /**
     * Destroys the repository class loader if existing and ungets the
     * DynamicClassLoaderManager service if a dynamic class loader is
     * being used.
     */
    private void destroyRepositoryClassLoader() {
        final RepositoryClassLoader rcl = this.repositoryClassLoader;
        if (rcl != null) {
            this.repositoryClassLoader = null;
            rcl.destroy();
            final ServiceReference localDynamicClassLoaderManager = this.dynamicClassLoaderManager;
            final Bundle localCallerBundle = this.callerBundle;
            if ( localDynamicClassLoaderManager != null && localCallerBundle != null ) {
                localCallerBundle.getBundleContext().ungetService(localDynamicClassLoaderManager);
            }
        }
    }

    /**
     * Return a new session.
     */
    public Session createSession() throws RepositoryException {
        // get an administrative session for potential impersonation
        final Session admin = this.repository.loginAdministrative(null);

        // do use the admin session, if the admin's user id is the same as owner
        if (admin.getUserID().equals(this.classLoaderOwner)) {
            return admin;
        }

        // else impersonate as the owner and logout the admin session again
        try {
            return admin.impersonate(new SimpleCredentials(this.classLoaderOwner, new char[0]));
        } finally {
            admin.logout();
        }
    }

    /**
     * Is this still active?
     */
    public boolean isActivate() {
        return this.repository != null;
    }

    private synchronized RepositoryClassLoader getOrCreateClassLoader() {
        if ( this.repositoryClassLoader == null || !this.repositoryClassLoader.isLive() ) {

            // make sure to cleanup any existing class loader
            this.destroyRepositoryClassLoader();

            // get the dynamic class loader for the bundle using this
            // class loader writer
            final DynamicClassLoaderManager dclm = (DynamicClassLoaderManager) this.callerBundle.getBundleContext().getService(
                this.dynamicClassLoaderManager);

            this.repositoryClassLoader = new RepositoryClassLoader(
                    this.classPath,
                    this,
                    dclm.getDynamicClassLoader());
        }
        return this.repositoryClassLoader;
    }

    private synchronized void handleChangeEvent(final String path) {
        final RepositoryClassLoader rcl = this.repositoryClassLoader;
        if ( rcl != null ) {
            rcl.handleEvent(path);
        }
    }

    /**
     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#delete(java.lang.String)
     */
    public boolean delete(final String name) {
        final String path = cleanPath(name);
        this.handleChangeEvent(path);
        Session session = null;
        try {
            session = createSession();
            if (session.itemExists(path)) {
                Item fileItem = session.getItem(path);
                fileItem.remove();
                session.save();
                return true;
            }
        } catch (final RepositoryException re) {
            logger.error("Cannot remove " + path, re);
        } finally {
            if ( session != null ) {
                session.logout();
            }
        }

        // fall back to false if item does not exist or in case of error
        return false;
    }

    /**
     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getOutputStream(java.lang.String)
     */
    public OutputStream getOutputStream(final String name) {
        final String path = cleanPath(name);
        return new RepositoryOutputStream(this, path);
    }

    /**
     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#rename(java.lang.String, java.lang.String)
     */
    public boolean rename(final String oldName, final String newName) {
        final String oldPath = cleanPath(oldName);
        final String newPath = cleanPath(newName);

        Session session = null;
        try {
            session = this.createSession();
            session.move(oldPath, newPath);
            session.save();

            this.handleChangeEvent(oldName);
            this.handleChangeEvent(newName);

            return true;
        } catch (final RepositoryException re) {
            logger.error("Cannot rename " + oldName + " to " + newName, re);
        } finally {
            if ( session != null ) {
                session.logout();
            }
        }

        // fall back to false in case of error or non-existence of oldFileName
        return false;
    }

    /**
     * Creates a folder hierarchy in the repository.
     * We synchronize this method to reduce potential conflicts.
     * Although each write uses its own session it might occur
     * that more than one session tries to create the same path
     * (or parent path) at the same time. By synchronizing this
     * we avoid this situation - however this method is written
     * in a fail safe manner anyway.
     */
    private synchronized boolean mkdirs(final Session session, final String path) {
        try {
            // quick test
            if (session.itemExists(path) && session.getItem(path).isNode()) {
                return true;
            }

            // check path walking it down
            Node current = session.getRootNode();
            final String[] names = path.split("/");
            for (int i = 0; i < names.length; i++) {
                if (names[i] == null || names[i].length() == 0) {
                    continue;
                } else if (current.hasNode(names[i])) {
                    current = current.getNode(names[i]);
                } else {
                    final Node parentNode = current;
                    try {
                        // adding the node could cause an exception
                        // for example if another thread tries to
                        // create the node "at the same time"
                        current = parentNode.addNode(names[i], NT_FOLDER);
                        session.save();
                    } catch (final RepositoryException re) {
                        // let's first refresh the session
                        // we don't catch an exception here, because if
                        // session refresh fails, we might have a serious problem!
                        session.refresh(false);
                        // let's check if the node is available now
                        if ( parentNode.hasNode(names[i]) ) {
                            current = parentNode.getNode(names[i]);
                        } else {
                            // we try it one more time to create the node - and fail otherwise
                            current = parentNode.addNode(names[i], NT_FOLDER);
                            session.save();
                        }
                    }
                }
            }

            return true;

        } catch (final RepositoryException re) {
            logger.error("Cannot create folder path:" + path, re);
            // discard changes
            try {
                session.refresh(false);
            } catch (final RepositoryException e) {
                // we simply ignore this
            }
        }

        // false in case of error or no need to create
        return false;
    }

    /**
     * Helper method to clean the path.
     * It replaces backslashes with slashes and cuts off trailing spaces.
     * It uses the first configured class path to access the path.
     */
    private String cleanPath(String path) {
        // replace backslash by slash
        path = path.replace('\\', '/');

        // cut off trailing slash
        while (path.endsWith("/")) {
            path = path.substring(0, path.length() - 1);
        }

        return this.classPath + path;
    }

    private static class RepositoryOutputStream extends ByteArrayOutputStream {

        private final ClassLoaderWriterImpl repositoryOutputProvider;

        private final String fileName;

        RepositoryOutputStream(ClassLoaderWriterImpl repositoryOutputProvider,
                String fileName) {
            this.repositoryOutputProvider = repositoryOutputProvider;
            this.fileName = fileName;
        }

        /**
         * @see java.io.ByteArrayOutputStream#close()
         */
        @Override
        public void close() throws IOException {
            super.close();

            Session session = null;
            try {
                // get an own session for writing
                session = repositoryOutputProvider.createSession();
                final int lastPos = fileName.lastIndexOf('/');
                final String path = (lastPos == -1 ? null : fileName.substring(0, lastPos));
                final String name = (lastPos == -1 ? fileName : fileName.substring(lastPos + 1));
                if ( lastPos != -1 ) {
                    if ( !repositoryOutputProvider.mkdirs(session, path) ) {
                        throw new IOException("Unable to create path for " + path);
                    }
                }
                Node fileNode = null;
                Node contentNode = null;
                Node parentNode = null;
                if (session.itemExists(fileName)) {
                    final Item item = session.getItem(fileName);
                    if (item.isNode()) {
                        final Node node = item.isNode() ? (Node) item : item.getParent();
                        if ("jcr:content".equals(node.getName())) {
                            // replace the content properties of the jcr:content
                            // node
                            parentNode = node;
                            contentNode = node;
                        } else if (node.isNodeType("nt:file")) {
                            // try to set the content properties of jcr:content
                            // node
                            parentNode = node;
                            contentNode = node.getNode("jcr:content");
                        } else { // fileName is a node
                            // try to set the content properties of the node
                            parentNode = node;
                            contentNode = node;
                        }
                    } else {
                        // replace property with an nt:file node (if possible)
                        parentNode = item.getParent();
                        item.remove();
                        session.save();
                        fileNode = parentNode.addNode(name, "nt:file");
                    }
                } else {
                    if (lastPos <= 0) {
                        parentNode = session.getRootNode();
                    } else {
                        Item parent = session.getItem(path);
                        if (!parent.isNode()) {
                            throw new IOException("Parent at " + path + " is not a node.");
                        }
                        parentNode = (Node) parent;
                    }
                    fileNode = parentNode.addNode(name, "nt:file");
                }

                // if we have a file node, create the contentNode
                if (fileNode != null) {
                    contentNode = fileNode.addNode("jcr:content", "nt:resource");
                }

                final MimeTypeService mtService = this.repositoryOutputProvider.mimeTypeService;

                String mimeType = (mtService == null ? null : mtService.getMimeType(fileName));
                if (mimeType == null) {
                    mimeType = "application/octet-stream";
                }

                contentNode.setProperty("jcr:lastModified", System.currentTimeMillis());
                contentNode.setProperty("jcr:data", new ByteArrayInputStream(buf, 0, size()));
                contentNode.setProperty("jcr:mimeType", mimeType);

                session.save();
                this.repositoryOutputProvider.handleChangeEvent(fileName);
            } catch (final RepositoryException re) {
                throw (IOException)new IOException("Cannot write file " + fileName + ", reason: " + re.toString()).initCause(re);
            } finally {
                if ( session != null ) {
                    session.logout();
                }
            }
        }
    }

    /**
     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getInputStream(java.lang.String)
     */
    public InputStream getInputStream(final String name)
    throws IOException {
        final String path = cleanPath(name) + "/jcr:content/jcr:data";
        Session session = null;
        try {
            session = this.createSession();
            if ( session.itemExists(path) ) {
                final Property prop = (Property)session.getItem(path);
                final InputStream is = prop.getStream();
                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int l = 0;
                final byte[] buf = new byte[2048];
                while ( (l = is.read(buf)) > -1 ) {
                    if ( l > 0 ) {
                        baos.write(buf, 0, l);
                    }
                }
                return new ByteArrayInputStream(baos.toByteArray());
            }
            throw new FileNotFoundException("Unable to find " + name);
        } catch (final RepositoryException re) {
            throw (IOException) new IOException(
                        "Failed to get InputStream for " + name).initCause(re);
        } finally {
            if ( session != null ) {
                session.logout();
            }
        }
    }

    /**
     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getLastModified(java.lang.String)
     */
    public long getLastModified(final String name) {
        final String path = cleanPath(name) + "/jcr:content/jcr:lastModified";
        Session session = null;
        try {
            session = this.createSession();
            if ( session.itemExists(path) ) {
                final Property prop = (Property)session.getItem(path);
                return prop.getLong();
            }
        } catch (final RepositoryException se) {
            logger.error("Cannot get last modification time for " + name, se);
        } finally {
            if ( session != null ) {
                session.logout();
            }
        }

        // fall back to "non-existent" in case of problems
        return -1;
    }

    /**
     * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getClassLoader()
     */
    public ClassLoader getClassLoader() {
        return this.getOrCreateClassLoader();
    }
}
