/*
 * 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 java.util.Map;

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.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
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.commons.osgi.PropertiesUtil;
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.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(metatype=true, label="%loader.name", description="%loader.description",
           name="org.apache.sling.jcr.classloader.internal.DynamicClassLoaderProviderImpl")
@Service(value = ClassLoaderWriter.class, serviceFactory = true)
@Properties({
    @org.apache.felix.scr.annotations.Property(name="service.vendor", value="The Apache Software Foundation"),
    @org.apache.felix.scr.annotations.Property(name="service.description", value="Repository based classloader writer")
})
public class ClassLoaderWriterImpl
    implements ClassLoaderWriter {

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

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

    @org.apache.felix.scr.annotations.Property(value=CLASS_PATH_DEFAULT)
    private static final String CLASS_PATH_PROP = "classpath";

    private static final boolean APPEND_ID_DEFAULT = true;

    @org.apache.felix.scr.annotations.Property(boolValue=APPEND_ID_DEFAULT)
    private static final String APPEND_ID_PROP = "appendId";

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

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

    @org.apache.felix.scr.annotations.Property(value=OWNER_DEFAULT)
    private static final String OWNER_PROP = "owner";

    @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_UNARY)
    private volatile MimeTypeService mimeTypeService;

    @Reference(
            referenceInterface = 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 properties The configuration properties
     */
    @Activate
    protected void activate(final ComponentContext componentContext, final Map<String, Object> properties) {
        this.classPath = PropertiesUtil.toString(properties.get(CLASS_PATH_PROP), CLASS_PATH_DEFAULT);
        if ( this.classPath.endsWith("/") ) {
            this.classPath = this.classPath.substring(0, this.classPath.length() - 1);
        }
        if ( PropertiesUtil.toBoolean(properties.get(APPEND_ID_PROP), APPEND_ID_DEFAULT) ) {
            this.classPath = this.classPath + '/' + this.settings.getSlingId();
        }

        this.classLoaderOwner = PropertiesUtil.toString(properties.get(OWNER_PROP), OWNER_DEFAULT);

        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();
    }
}
