/*
 * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 * Copyright 2021 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.weld.connector;

import com.sun.enterprise.config.serverbeans.Config;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.classmodel.reflect.AnnotationModel;
import org.glassfish.hk2.classmodel.reflect.AnnotationType;
import org.glassfish.hk2.classmodel.reflect.Type;
import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.deployment.ExtendedDeploymentContext;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import jakarta.decorator.Decorator;
import jakarta.ejb.MessageDriven;
import jakarta.ejb.Stateful;
import jakarta.ejb.Stateless;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.NormalScope;
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.context.SessionScoped;
import jakarta.enterprise.inject.Stereotype;
import jakarta.inject.Scope;
import jakarta.inject.Singleton;
import jakarta.interceptor.Interceptor;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class WeldUtils {

    public static final char SEPARATOR_CHAR = '/';
    public static final String WEB_INF = "WEB-INF";
    public static final String WEB_INF_CLASSES = WEB_INF + SEPARATOR_CHAR + "classes";
    public static final String WEB_INF_LIB = WEB_INF + SEPARATOR_CHAR + "lib";

    public static final String BEANS_XML_FILENAME = "beans.xml";
    public static final String WEB_INF_BEANS_XML = WEB_INF + SEPARATOR_CHAR + BEANS_XML_FILENAME;
    public static final String META_INF_BEANS_XML = "META-INF" + SEPARATOR_CHAR + BEANS_XML_FILENAME;
    public static final String WEB_INF_CLASSES_META_INF_BEANS_XML = WEB_INF_CLASSES + SEPARATOR_CHAR + META_INF_BEANS_XML;

    private static final String SERVICES_DIR = "services";

    // We don't want this connector module to depend on CDI API, as connector can be present in a distribution
    // which does not have CDI implementation. So, we use the class name as a string.
    private static final String SERVICES_CLASSNAME = "jakarta.enterprise.inject.spi.Extension";
    public static final String META_INF_SERVICES_EXTENSION =
        "META-INF" + SEPARATOR_CHAR + SERVICES_DIR + SEPARATOR_CHAR + SERVICES_CLASSNAME;

    public static final String CLASS_SUFFIX = ".class";
    public static final String JAR_SUFFIX = ".jar";
    public static final String RAR_SUFFIX = ".rar";
    public static final String EXPANDED_RAR_SUFFIX = "_rar";
    public static final String EXPANDED_JAR_SUFFIX = "_jar";

    public static enum BDAType { WAR, JAR, RAR, UNKNOWN };

    // The name of the deployment context property used to disable implicit bean discovery for a
    // particular application deployment.
    public static final String IMPLICIT_CDI_ENABLED_PROP = "implicitCdiEnabled";

    private static final List<String> cdiScopeAnnotations;
    static {
        cdiScopeAnnotations = new ArrayList<String>();
        cdiScopeAnnotations.add(Scope.class.getName());
        cdiScopeAnnotations.add(NormalScope.class.getName());
        cdiScopeAnnotations.add(ApplicationScoped.class.getName());
        cdiScopeAnnotations.add(SessionScoped.class.getName());
        cdiScopeAnnotations.add(RequestScoped.class.getName());
        cdiScopeAnnotations.add(Dependent.class.getName());
        cdiScopeAnnotations.add(Singleton.class.getName());
    }

    private static final List<String> cdiEnablingAnnotations;
    static {
        cdiEnablingAnnotations = new ArrayList<String>();

        // CDI scopes
        cdiEnablingAnnotations.addAll(cdiScopeAnnotations);

        // 1.2 updates
       cdiEnablingAnnotations.add(Decorator.class.getName());
       cdiEnablingAnnotations.add(Interceptor.class.getName());
       cdiEnablingAnnotations.add(Stereotype.class.getName());

        // EJB annotations
        cdiEnablingAnnotations.add(MessageDriven.class.getName());
        cdiEnablingAnnotations.add(Stateful.class.getName());
        cdiEnablingAnnotations.add(Stateless.class.getName());
        cdiEnablingAnnotations.add(jakarta.ejb.Singleton.class.getName());
    }

    /**
     * Determine whether the specified archive is an implicit bean deployment archive.
     *
     * @param context  The deployment context
     * @param archive  The archive in question
     *
     * @return true, if it is an implicit bean deployment archive; otherwise, false.
     */
    public static boolean isImplicitBeanArchive(DeploymentContext context, ReadableArchive archive)
            throws IOException {
        boolean result = false;

         //refer CDI 2.0 spec section 12.1
        // Archives with extensions and no beans.xml file are not candidates for implicit bean discovery
        if (!archive.exists(META_INF_SERVICES_EXTENSION)) {
          result = isImplicitBeanArchive(context, archive.getURI());
        } else {

            if (archive.exists(META_INF_BEANS_XML)) {

                result = isImplicitBeanArchive(context, archive.getURI());
            }

        }

        return result;
    }

    /**
     * Determine whether the specified archive is an implicit bean deployment archive.
     *
     * @param context     The deployment context
     * @param archivePath The URI of the archive
     *
     * @return true, if it is an implicit bean deployment archive; otherwise, false.
     */
    public static boolean isImplicitBeanArchive(DeploymentContext context, URI archivePath) {
        return (isImplicitBeanDiscoveryEnabled(context) && hasCDIEnablingAnnotations(context, archivePath));
    }


    /**
     * Determine whether there are any beans annotated with annotations that should enable CDI
     * processing even in the absence of a beans.xml descriptor.
     *
     * @param context The DeploymentContext
     * @param path    The path to check for annotated beans
     *
     * @return true, if there is at least one bean annotated with a qualified annotation in the specified path
     */
    public static boolean hasCDIEnablingAnnotations(DeploymentContext context, URI path) {
        Set<URI> paths = new HashSet<URI>();
        paths.add(path);
        return hasCDIEnablingAnnotations(context, paths);
    }


    /**
     * Determine whether there are any beans annotated with annotations that should enable CDI
     * processing even in the absence of a beans.xml descriptor.
     *
     * @param context The DeploymentContext
     * @param paths   The paths to check for annotated beans
     *
     * @return true, if there is at least one bean annotated with a qualified annotation in the specified paths
     */
    public static boolean hasCDIEnablingAnnotations(DeploymentContext context, Collection<URI> paths) {
        List<String> result = new ArrayList<String>();

        Types types = getTypes(context);
        if (types != null) {
            Iterator<Type> typesIter = types.getAllTypes().iterator();
            while (typesIter.hasNext()) {
                Type type = typesIter.next();
                if (!(type instanceof AnnotationType)) {
                    Iterator<AnnotationModel> annotations = type.getAnnotations().iterator();
                    while (annotations.hasNext()) {
                        AnnotationModel am = annotations.next();
                        AnnotationType at = am.getType();
                        if (isCDIEnablingAnnotation(at) && type.wasDefinedIn(paths)) {
                            if (!result.contains(at.getName())) {
                                result.add(at.getName());
                            }
                        }
                    }
                }
            }
        }

        return !(result.isEmpty());
    }


    /**
     * Get the names of any annotation types that are applied to beans, which should enable CDI
     * processing even in the absence of a beans.xml descriptor.
     *
     * @param context The DeploymentContext
     *
     * @return An array of annotation type names; The array could be empty if none are found.
     */
    public static String[] getCDIEnablingAnnotations(DeploymentContext context) {
        List<String> result = new ArrayList<String>();

        Types types = getTypes(context);
        if (types != null) {
            Iterator<Type> typesIter = types.getAllTypes().iterator();
            while (typesIter.hasNext()) {
                Type type = typesIter.next();
                if (!(type instanceof AnnotationType)) {
                    Iterator<AnnotationModel> annotations = type.getAnnotations().iterator();
                    while (annotations.hasNext()) {
                        AnnotationModel am = annotations.next();
                        AnnotationType at = am.getType();
                        if (isCDIEnablingAnnotation(at)) {
                            if (!result.contains(at.getName())) {
                                result.add(at.getName());
                            }
                        }
                    }
                }
            }
        }

        return result.toArray(new String[result.size()]);
    }


    /**
     * Get the names of any classes that are annotated with bean-defining annotations, which should
     * enable CDI processing even in the absence of a beans.xml descriptor.
     *
     * @param context The DeploymentContext
     *
     * @return A collection of class names; The collection could be empty if none are found.
     */
    public static Collection<String> getCDIAnnotatedClassNames(DeploymentContext context) {
        Set<String> result = new HashSet<String>();

        Types types = getTypes(context);
        if (types != null) {
            Iterator<Type> typesIter = types.getAllTypes().iterator();
            while (typesIter.hasNext()) {
                Type type = typesIter.next();
                if (!(type instanceof AnnotationType)) {
                    Iterator<AnnotationModel> annotations = type.getAnnotations().iterator();
                    while (annotations.hasNext()) {
                        AnnotationModel am = annotations.next();
                        AnnotationType at = am.getType();
                        if (isCDIEnablingAnnotation(at)) {
                            if (!result.contains(at.getName())) {
                                result.add(type.getName());
                            }
                        }
                    }
                }
            }
        }

        return result;
    }


    /**
     * Determine whether the specified class is annotated with a CDI scope annotation.
     *
     * @param clazz  The class to check.
     *
     * @return true, if the specified class has a CDI scope annotation; Otherwise, false.
     */
    public static boolean hasScopeAnnotation(Class clazz) {
        return hasValidAnnotation(clazz, cdiScopeAnnotations, null);
    }


    /**
     * Determine whether the specified class is annotated with a CDI-enabling annotation.
     *
     * @param clazz The class to check.
     *
     * @return true, if the specified class has a CDI scope annotation; Otherwise, false.
     */
    public static boolean hasCDIEnablingAnnotation(Class clazz) {
        return hasValidAnnotation(clazz, cdiEnablingAnnotations, null);
    }


    /**
     * Determine if the specified annotation type is a CDI-enabling annotation
     *
     * @param annotationType The annotation type to check
     *
     * @return true, if the specified annotation type qualifies as a CDI enabler; Otherwise, false
     */
    private static boolean isCDIEnablingAnnotation(AnnotationType annotationType) {
        return isCDIEnablingAnnotation(annotationType, null);
    }


    /**
     * Determine if the specified annotation type is a CDI-enabling annotation
     *
     * @param annotationType    The annotation type to check
     * @param excludedTypeNames The Set of annotation type names that should be excluded from the analysis
     *
     * @return true, if the specified annotation type qualifies as a CDI enabler; Otherwise, false
     */
    private static boolean isCDIEnablingAnnotation(AnnotationType annotationType,
                                                   Set<String>    excludedTypeNames) {
        boolean result = false;

        Set<String> exclusions = new HashSet<String>();
        if (excludedTypeNames != null) {
            exclusions.addAll(excludedTypeNames);
        }

        String annotationTypeName = annotationType.getName();
        if (cdiEnablingAnnotations.contains(annotationTypeName) && !exclusions.contains(annotationTypeName)) {
            result = true;
        } else if (!exclusions.contains(annotationTypeName)) {
            // If the annotation type itself is not an excluded type, then check it's annotation
            // types, less itself (to avoid infinite recursion)
            exclusions.add(annotationTypeName);
            for (AnnotationModel parent : annotationType.getAnnotations()) {
                if (isCDIEnablingAnnotation(parent.getType(), exclusions)) {
                    result = true;
                    break;
                }
            }
        }

        return result;
    }


    /**
     * Determine whether the specified class is annotated with one of the annotations in the specified
     * validScopes collection, but not with any of the annotations in the specified exclusion set.
     *
     * @param annotatedClass          The class to check.
     * @param validScopes    A collection of valid CDI scope type names
     * @param excludedScopes A collection of excluded CDI scope type names
     *
     * @return true, if the specified class has at least one of the annotations specified in
     *         validScopes, and none of the annotations specified in excludedScopes; Otherwise, false.
     */
    public static boolean hasValidAnnotation(Class              annotatedClass,
                                             Collection<String> validScopes,
                                             Collection<String> excludedScopes) {
        boolean result = false;

        // Check all the annotations on the specified Class to determine if the class is annotated
        // with a supported CDI scope
        for (Annotation annotation : annotatedClass.getAnnotations()) {
            if (WeldUtils.isValidAnnotation(annotation.annotationType(),
                                            validScopes,
                                            excludedScopes)) {
                result =true;
                break;
            }
        }

        return result;
    }

    /**
     * Determine whether the specified annotation type is one of the specified valid types and not
     * in the specified exclusion list. Positive results include those annotations which are themselves
     * annotated with types in the valid list.
     *
     * @param annotationType     The annotation type to check
     * @param validTypeNames     The valid annotation type names
     * @param excludedTypeNames  The excluded annotation type names
     *
     * @return true, if the specified type is in the valid list and not in the excluded list; Otherwise, false.
     */
    protected static boolean isValidAnnotation(Class<? extends Annotation> annotationType,
                                               Collection<String>          validTypeNames,
                                               Collection<String>          excludedTypeNames) {
        boolean result = false;

        if (validTypeNames != null && !validTypeNames.isEmpty()) {

            HashSet<String> excludedScopes = new HashSet<String>();
            if (excludedTypeNames != null) {
                excludedScopes.addAll(excludedTypeNames);
            }

            String annotationTypeName = annotationType.getName();
            if (validTypeNames.contains(annotationTypeName) && !excludedScopes.contains(annotationTypeName)) {
                result = true;
            } else if (!excludedScopes.contains(annotationTypeName)){
                // If the annotation type itself is not an excluded type, then check it's annotation
                // types, less itself (to avoid infinite recursion)
                excludedScopes.add(annotationTypeName);
                for (Annotation parent : annotationType.getAnnotations()) {
                    if (isValidAnnotation(parent.annotationType(), validTypeNames, excludedScopes)) {
                        result = true;
                        break;
                    }
                }
            }
        }

        return result;
    }


    private static Types getTypes(DeploymentContext context) {
        String metadataKey = Types.class.getName();

        Types types = (Types) context.getTransientAppMetadata().get(metadataKey);
        while (types == null) {
            context = ((ExtendedDeploymentContext) context).getParentContext();
            if (context != null) {
                types = (Types) context.getTransientAppMetadata().get(metadataKey);
            } else {
                break;
            }
        }

        return types;
    }


    public static boolean isImplicitBeanDiscoveryEnabled() {
        boolean result = false;

        // Check the "global" configuration
        ServiceLocator serviceLocator = Globals.getDefaultHabitat();
        if (serviceLocator != null) {
            Config config = serviceLocator.getService(Config.class, ServerEnvironment.DEFAULT_INSTANCE_NAME);
            if (config != null) {
                result = Boolean.valueOf(config.getExtensionByType(CDIService.class).getEnableImplicitCdi());
            }
        }

        return result;
    }


    public static boolean isImplicitBeanDiscoveryEnabled(DeploymentContext context) {
        boolean result = false;

        if (isImplicitBeanDiscoveryEnabled()) {
            // If implicit discovery is enabled for the server, then check if it's disabled for the
            // deployment of this application.
            Object propValue = context.getAppProps().get(IMPLICIT_CDI_ENABLED_PROP);

            // If the property is not set, or it's value is true, then implicit discovery is enabled
            result = (propValue == null || Boolean.parseBoolean((String) propValue));
        }

        return result;
    }


  public static InputStream getBeansXmlInputStream(DeploymentContext context) {
    return getBeansXmlInputStream( context.getSource() );
  }

  /**
   * Determine if an archive is a valid bda based on what the spec says about extensions.
   * See section 12.1 which states that if an archive contains an extension but no beans.xml then it is NOT
   * a valid bean deployment archive.
   *
   * @param archive The archive to check.
   * @return false if there is an extension and no beans.xml
   *         true otherwise
   */
  public static boolean isValidBdaBasedOnExtensionAndBeansXml( ReadableArchive archive ) {
    boolean retVal = true;

    try {
      if ( archive.exists(META_INF_SERVICES_EXTENSION)) {
        retVal = false;
        InputStream inputStream = getBeansXmlInputStream( archive );
        if ( inputStream != null ) {
          retVal = true;  // is a valid bda
          try {
            inputStream.close();
          } catch (IOException ignore) {
          }
        }
      }
    } catch (IOException ignore) {
    }

    return retVal;
  }


  public static InputStream getBeansXmlInputStream( ReadableArchive archive ) {
    InputStream inputStream = null;

    try {
      if (archive.exists(WeldUtils.WEB_INF)) {
        inputStream = archive.getEntry(WeldUtils.WEB_INF_BEANS_XML);
        if (inputStream == null) {
          inputStream = archive.getEntry(WeldUtils.WEB_INF_CLASSES_META_INF_BEANS_XML);
        }
      } else {
        inputStream = archive.getEntry(WeldUtils.META_INF_BEANS_XML);
      }
    } catch (IOException e) {
      return null;
    }
    return inputStream;
  }

  /**
   * Get the "bean-discovery-mode" from the "beans" element if it exists in beans.xml
   * From section 12.1 of CDI spec:
   * A bean archive has a bean discovery mode of all, annotated or none. A bean archive which
   * contains a beans.xml file with no version has a default bean discovery mode of all. A bean
   * archive which contains a beans.xml file with version 1.1 (or later) must specify the bean-
   * discovey-mode attribute. The default value for the attribute is annotated.
   *
   * @param beansXmlInputStream The InputStream for the beans.xml to check.
   * @return "annotated" if there is no beans.xml
   *         "all" if the bean-discovery-mode is missing
   *         "annotated" if the bean-discovery-mode is empty
   *         The value of bean-discovery-mode in all other cases.
   */
    public static String getBeanDiscoveryMode( InputStream beansXmlInputStream ) {
      if ( beansXmlInputStream == null ) {
        // there is no beans.xml.
        return "annotated";
      }

      String beanDiscoveryMode = null;
      LocalDefaultHandler handler = new LocalDefaultHandler();
      try {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser saxParser = factory.newSAXParser();
        saxParser.parse(beansXmlInputStream, handler);
      } catch ( SAXStoppedIntentionallyException exc ) {
        beanDiscoveryMode = handler.getBeanDiscoveryMode();
      } catch (Exception ignore) {
      }

      if (beanDiscoveryMode == null ) {
        return "all";
      } else if (beanDiscoveryMode.equals("")) {
        return "annotated";
      } else {
        return beanDiscoveryMode;
      }
    }

    private static class LocalDefaultHandler extends DefaultHandler {
        String beanDiscoveryMode = null;

        public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {
            if ( qName.equals( "beans" ) ) {
                beanDiscoveryMode = attributes.getValue("bean-discovery-mode");
                if ( beanDiscoveryMode != null ) {
                  if ( beanDiscoveryMode.equals( "" ) ) {
                    beanDiscoveryMode = "annotated";
                  }
                }
                throw new SAXStoppedIntentionallyException();
            }
        }

        public String getBeanDiscoveryMode() {
            return beanDiscoveryMode;
        }
    }

    private static class SAXStoppedIntentionallyException extends SAXException {
        private SAXStoppedIntentionallyException() {
            super();
        }
    }


}
