/*
 * 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.felix.scrplugin;


import java.io.*;
import java.util.*;
import java.util.jar.*;

import org.apache.felix.scrplugin.om.Component;
import org.apache.felix.scrplugin.om.Components;
import org.apache.felix.scrplugin.tags.JavaClassDescription;
import org.apache.felix.scrplugin.tags.JavaTag;
import org.apache.felix.scrplugin.tags.annotation.AnnotationJavaClassDescription;
import org.apache.felix.scrplugin.tags.annotation.AnnotationTagProviderManager;
import org.apache.felix.scrplugin.tags.cl.ClassLoaderJavaClassDescription;
import org.apache.felix.scrplugin.tags.qdox.QDoxJavaClassDescription;
import org.apache.felix.scrplugin.xml.ComponentDescriptorIO;

import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaSource;


/**
 * The <code>JavaClassDescriptorManager</code> must be implemented to provide
 * access to the java sources to be scanned for descriptor annotations and
 * JavaDoc tags, the descriptors of components from the class path and the
 * location of the generated class files to be able to add the bind and unbind
 * methods.
 */
public abstract class JavaClassDescriptorManager
{

    /** The maven log. */
    protected final Log log;

    /** The classloader used to compile the classes. */
    private final ClassLoader classloader;

    /** A cache containing the java class descriptions hashed by classname. */
    private final Map<String, JavaClassDescription> javaClassDescriptions = new HashMap<String, JavaClassDescription>();

    /**
     * Supports mapping of built-in and custom java anntoations to
     * {@link JavaTag} implementations.
     */
    private final AnnotationTagProviderManager annotationTagProviderManager;

    /** Parse Javadocs? */
    private final boolean parseJavadocs;

    /** Process Annotations? */
    private final boolean processAnnotations;

    /** The Java sources gathered by {@link #getSourceDescriptions()} */
    private JavaSource[] sources;

    /** The component definitions from other bundles hashed by classname. */
    private Map<String, Component> componentDescriptions;


    /**
     * Construct a new manager.
     *
     * @throws SCRDescriptorFailureException
     */
    public JavaClassDescriptorManager( final Log log, final ClassLoader classLoader,
        final String[] annotationTagProviders, final boolean parseJavadocs, final boolean processAnnotations )
        throws SCRDescriptorFailureException
    {
        this.processAnnotations = processAnnotations;
        this.parseJavadocs = parseJavadocs;
        this.log = log;
        this.annotationTagProviderManager = new AnnotationTagProviderManager( annotationTagProviders, classLoader );
        this.classloader = classLoader;
    }


    /**
     * Returns the QDox JavaSource instances representing the source files for
     * which the Declarative Services and Metatype descriptors have to be
     * generated.
     *
     * @throws SCRDescriptorException May be thrown if an error occurrs
     *             gathering the java sources.
     */
    protected JavaSource[] getSources() throws SCRDescriptorException
    {
        if ( this.sources == null )
        {
            this.log.debug( "Setting up QDox" );

            JavaDocBuilder builder = new JavaDocBuilder();
            builder.getClassLibrary().addClassLoader( this.getClassLoader() );

            final Iterator<File> i = getSourceFiles();
            while ( i.hasNext() )
            {
                File file = i.next();
                this.log.debug( "Adding source file " + file );
                try
                {
                    builder.addSource( file );
                }
                catch ( IOException e )
                {
                    // also FileNotFoundException
                    throw new SCRDescriptorException( "Unable to add source file", file.toString(), 0, e );
                }
            }
            this.sources = builder.getSources();
        }

        return this.sources;
    }


    /**
     * Returns an iterator of paths to directories providing Java source files
     * to be parsed.
     * <p>
     * This method is called by the default {@link #getSources()} implementation
     * to return the root directories for the Java files to be parsed. This
     * default implementation returns an empty iterator. Implementations of this
     * class not overwriting the {@link #getSources()} method should overwrite
     * this method by providing the concrete source locations.
     *
     * @return An iterator of Java source locations.
     */
    protected Iterator<File> getSourceFiles()
    {
        return Collections.<File> emptyList().iterator();
    }


    /**
     * Returns a map of component descriptors which may be extended by the java
     * sources returned by the {@link #getSources()} method.
     * <p>
     * This method calls the {@link #getDependencies()} method and checks for
     * any Service-Component descriptors in the returned files.
     * <p>
     * This method may be overwritten by extensions of this class.
     *
     * @throws SCRDescriptorException May be thrown if an error occurrs
     *             gethering the component descriptors.
     */
    protected Map<String, Component> getComponentDescriptors() throws SCRDescriptorException
    {
        if ( this.componentDescriptions == null )
        {
            final List<Component> components = new ArrayList<Component>();
            final List<File> dependencies = getDependencies();
            for ( File artifact : dependencies )
            {
                this.log.debug( "Trying to get manifest from artifact " + artifact );
                try
                {
                    final Manifest manifest = this.getManifest( artifact );
                    if ( manifest != null )
                    {
                        // read Service-Component entry
                        if ( manifest.getMainAttributes().getValue( Constants.SERVICE_COMPONENT ) != null )
                        {
                            final String serviceComponent = manifest.getMainAttributes().getValue(
                                Constants.SERVICE_COMPONENT );
                            this.log
                                .debug( "Found Service-Component: " + serviceComponent + " in artifact " + artifact );
                            final StringTokenizer st = new StringTokenizer( serviceComponent, "," );
                            while ( st.hasMoreTokens() )
                            {
                                final String entry = st.nextToken().trim();
                                if ( entry.length() > 0 )
                                {
                                    final Components c = this.readServiceComponentDescriptor( artifact, entry );
                                    if ( c != null )
                                    {
                                        components.addAll( c.getComponents() );
                                    }
                                }
                            }
                        }
                        else
                        {
                            this.log.debug( "Artifact has no service component entry in manifest " + artifact );
                        }
                    }
                    else
                    {
                        this.log.debug( "Unable to get manifest from artifact " + artifact );
                    }
                }
                catch ( IOException ioe )
                {
                    throw new SCRDescriptorException( "Unable to get manifest from artifact", artifact.toString(), 0,
                        ioe );
                }
                this.log.debug( "Trying to get scrinfo from artifact " + artifact );
                // now read the scr private file - components stored there
                // overwrite components already
                // read from the service component section.
                InputStream scrInfoFile = null;
                try
                {
                    scrInfoFile = this.getFile( artifact, Constants.ABSTRACT_DESCRIPTOR_ARCHIV_PATH );
                    if ( scrInfoFile != null )
                    {
                        components.addAll( this.parseServiceComponentDescriptor( scrInfoFile ).getComponents() );
                    }
                    else
                    {
                        this.log.debug( "Artifact has no scrinfo file (it's optional): " + artifact );
                    }
                }
                catch ( IOException ioe )
                {
                    throw new SCRDescriptorException( "Unable to get scrinfo from artifact", artifact.toString(), 0,
                        ioe );
                }
                finally
                {
                    if ( scrInfoFile != null )
                    {
                        try
                        {
                            scrInfoFile.close();
                        }
                        catch ( IOException ignore )
                        {
                        }
                    }
                }

                // now create map with component descriptions
                this.componentDescriptions = new HashMap<String, Component>();
                for ( final Component component : components )
                {
                    this.componentDescriptions.put( component.getImplementation().getClassame(), component );
                }
            }
        }

        return this.componentDescriptions;
    }


    /**
     * Returns a list of files denoting dependencies of the module for which
     * descriptors are to be generated. The returned dependencies are expected
     * to be bundles which may (or may not) contain Service Component
     * descriptors (or internal descriptors in the case of abstract components
     * not listed in the "official" descriptors).
     * <p>
     * This method is called by the {@link #getComponentDescriptors()} method in
     * this class to get the list of bundles from where base component
     * descriptors are to be extracted.
     * <p>
     * Extensions of this class not overwriting the
     * {@link #getComponentDescriptors()} method should overwrite this method if
     * they wish to provide such base component descriptors.
     *
     * @return
     */
    protected List<File> getDependencies()
    {
        return Collections.<File> emptyList();
    }


    /**
     * Returns the absolute filesystem path to the directory where the classes
     * compiled from the java source files (see {@link #getSources()}) have been
     * placed.
     * <p>
     * This method is called to find the class files to which bind and unbind
     * methods are to be added.
     */
    public abstract String getOutputDirectory();


    /**
     * Return the log.
     */
    public Log getLog()
    {
        return this.log;
    }


    /**
     * Return the class laoder.
     */
    public ClassLoader getClassLoader()
    {
        return this.classloader;
    }


    /**
     * @return Annotation tag provider manager
     */
    public AnnotationTagProviderManager getAnnotationTagProviderManager()
    {
        return this.annotationTagProviderManager;
    }


    /**
     * Returns <code>true</code> if this class descriptor manager is parsing
     * JavaDoc tags.
     */
    public boolean isParseJavadocs()
    {
        return parseJavadocs;
    }


    /**
     * Returns <code>true</code> if this class descriptor manager is parsing
     * Java 5 annotations.
     */
    public boolean isProcessAnnotations()
    {
        return processAnnotations;
    }


    /**
     * Parses the descriptors read from the given input stream. This method may
     * be called by the {@link #getComponentDescriptors()} method to parse the
     * descriptors gathered in an implementation dependent way.
     *
     * @throws SCRDescriptorException If an error occurrs reading the
     *             descriptors from the stream.
     */
    protected Components parseServiceComponentDescriptor( InputStream file ) throws SCRDescriptorException
    {
        return ComponentDescriptorIO.read( file );
    }


    /**
     * Return all source descriptions of this project.
     *
     * @return All contained java class descriptions.
     */
    public JavaClassDescription[] getSourceDescriptions() throws SCRDescriptorException
    {
        final JavaClass[] javaClasses = getJavaClassesFromSources();
        final JavaClassDescription[] descs = new JavaClassDescription[javaClasses.length];
        for ( int i = 0; i < javaClasses.length; i++ )
        {
            descs[i] = this.getJavaClassDescription( javaClasses[i].getFullyQualifiedName() );
        }
        return descs;
    }

    private boolean doingHasScrPluginAnnotationCheck = false;

    private boolean hasScrPluginAnnotation(final Class<?> clazz, final JavaClass javaClass)
    {
        boolean result;
        doingHasScrPluginAnnotationCheck = true;

        result = getAnnotationTagProviderManager().hasScrPluginAnnotation( javaClass,
                new AnnotationJavaClassDescription( clazz, javaClass, this ));
        doingHasScrPluginAnnotationCheck = false;
        return result;
    }

    /**
     * Get a java class description for the class.
     *
     * @param className
     * @return The java class description.
     * @throws SCRDescriptorException
     */
    public JavaClassDescription getJavaClassDescription( String className ) throws SCRDescriptorException
    {
        JavaClassDescription result = this.javaClassDescriptions.get( className );
        if ( result == null )
        {
            this.log.debug( "Searching description for: " + className );
            int index = 0;
            final JavaClass[] javaClasses = getJavaClassesFromSources();
            while ( result == null && index < javaClasses.length )
            {
                final JavaClass javaClass = javaClasses[index];
                if ( javaClass.getFullyQualifiedName().equals( className ) )
                {
                    try
                    {
                        // check for java annotation descriptions - fallback to
                        // QDox if none found
                        Class<?> clazz = this.classloader.loadClass( className );
                        if ( this.processAnnotations && !doingHasScrPluginAnnotationCheck
                            && hasScrPluginAnnotation(clazz, javaClass) )
                        {
                            this.log.debug( "Found java annotation description for: " + className );
                            result = new AnnotationJavaClassDescription( clazz, javaClass, this );
                        }
                        else if ( this.parseJavadocs )
                        {
                            this.log.debug( "Found qdox description for: " + className );
                            result = new QDoxJavaClassDescription( clazz, javaClass, this );
                        }
                    }
                    catch ( ClassNotFoundException e )
                    {
                        throw new SCRDescriptorException( "Unable to load class", className, 0 );
                    }
                }
                else
                {
                    index++;
                }
            }
            if ( result == null )
            {
                try
                {
                    this.log.debug( "Generating classloader description for: " + className );
                    result = new ClassLoaderJavaClassDescription( this.classloader.loadClass( className ), this
                        .getComponentDescriptors().get( className ), this );
                }
                catch ( ClassNotFoundException e )
                {
                    throw new SCRDescriptorException( "Unable to load class", className, 0 );
                }
            }
            if ( !doingHasScrPluginAnnotationCheck ) {
                this.javaClassDescriptions.put( className, result );
            }
        }
        return result;
    }


    /**
     * Get a list of all {@link JavaClass} definitions four all source files
     * (including nested/inner classes)
     *
     * @return List of {@link JavaClass} definitions
     */
    private JavaClass[] getJavaClassesFromSources() throws SCRDescriptorException
    {
        final JavaSource[] sources = this.getSources();
        final List<JavaClass> classes = new ArrayList<JavaClass>();
        for ( int i = 0; i < sources.length; i++ )
        {
            if ( sources[i].getClasses() == null || sources[i].getClasses().length == 0 )
            {
                continue;
            }
            for ( int j = 0; j < sources[i].getClasses().length; j++ )
            {
                final JavaClass clazz = sources[i].getClasses()[j];
                classes.add( clazz );
                for ( int k = 0; k < clazz.getNestedClasses().length; k++ )
                {
                    final JavaClass nestedClass = clazz.getNestedClasses()[k];
                    classes.add( nestedClass );
                }
            }
        }
        return classes.toArray( new JavaClass[classes.size()] );
    }


    /**
     * Read the service component description.
     *
     * @param artifact
     * @param entry
     * @throws IOException
     * @throws SCRDescriptorException
     */
    private Components readServiceComponentDescriptor( final File artifactFile, String entry )
    {
        this.log.debug( "Reading " + entry + " from " + artifactFile );
        InputStream xml = null;
        try
        {
            xml = this.getFile( artifactFile, entry );
            if ( xml == null )
            {
                throw new SCRDescriptorException( "Entry " + entry + " not contained in JAR File ", artifactFile.toString(),
                    0 );
            }
            return this.parseServiceComponentDescriptor( xml );
        }
        catch ( IOException mee )
        {
            this.log.warn( "Unable to read SCR descriptor file from JAR File " + artifactFile + " at " + entry );
            this.log.debug( "Exception occurred during reading: " + mee.getMessage(), mee );
        }
        catch ( SCRDescriptorException mee )
        {
            this.log.warn( "Unable to read SCR descriptor file from JAR File " + artifactFile + " at " + entry );
            this.log.debug( "Exception occurred during reading: " + mee.getMessage(), mee );
        }
        finally
        {
            if ( xml != null )
            {
                try
                {
                    xml.close();
                }
                catch ( IOException ignore )
                {
                }
            }
        }
        return null;
    }


    private Manifest getManifest( File artifact ) throws IOException
    {
        if ( artifact.isDirectory() )
        {
            // this is maybe a classes directory, try to read manifest file directly
            final File dir = new File(artifact, "META-INF");
            if ( !dir.exists() || !dir.isDirectory() )
            {
                return null;
            }
            final File mf = new File(dir, "MANIFEST.MF");
            if ( !mf.exists() || !mf.isFile() )
            {
                return null;
            }
            final InputStream is = new FileInputStream(mf);
            try
            {
                return new Manifest(is);
            }
            finally
            {
                try
                {
                    is.close();
                }
                catch (final IOException ignore) { }
            }
        }
        JarFile file = null;
        try
        {
            file = new JarFile( artifact );
            return file.getManifest();
        }
        finally
        {
            if ( file != null )
            {
                try
                {
                    file.close();
                }
                catch ( IOException ignore )
                {
                }
            }
        }
    }


    private InputStream getFile( final File artifactFile, final String path ) throws IOException
    {
        if ( artifactFile.isDirectory() )
        {
            final String filePath = path.replace('/', File.separatorChar).replace('\\', File.separatorChar);
            final File file = new File(artifactFile, filePath);
            if ( file.exists() && file.isFile() )
            {
                return new FileInputStream(file);
            }
            return null;
        }
        JarFile file = null;
        try
        {
            file = new JarFile( artifactFile );
            final JarEntry entry = file.getJarEntry( path );
            if ( entry != null )
            {
                final InputStream stream = new ArtifactFileInputStream( file, entry );
                file = null; // prevent file from being closed now
                return stream;
            }
            return null;
        }
        finally
        {
            if ( file != null )
            {
                try
                {
                    file.close();
                }
                catch ( IOException ignore )
                {
                }
            }
        }
    }

    private static class ArtifactFileInputStream extends FilterInputStream
    {
        final JarFile jarFile;


        ArtifactFileInputStream( JarFile jarFile, JarEntry jarEntry ) throws IOException
        {
            super( jarFile.getInputStream( jarEntry ) );
            this.jarFile = jarFile;
        }


        @Override
        public void close() throws IOException
        {
            try
            {
                super.close();
            }
            catch ( IOException ioe )
            {
            }
            jarFile.close();
        }


        @Override
        protected void finalize() throws Throwable
        {
            try
            {
                close();
            }
            finally
            {
                super.finalize();
            }
        }
    }

}
