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

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.apache.commons.collections.CollectionUtils;
import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.Declarable;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.management.internal.deployment.FunctionScanner;
import org.apache.geode.pdx.internal.TypeRegistry;

/**
 * ClassLoader for a single JAR file.
 *
 * @since GemFire 7.0
 */
public class DeployedJar {

  private static final Logger logger = LogService.getLogger();
  @MakeNotStatic("This object gets updated in the production code")
  private static final MessageDigest messageDigest = getMessageDigest();
  private static final Pattern PATTERN_SLASH = Pattern.compile("/");

  private final String artifactId;
  private final File file;
  private final byte[] md5hash;
  private final Collection<Function> registeredFunctions = new ArrayList<>();

  private static MessageDigest getMessageDigest() {
    try {
      return MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException ignored) {
      // Failure just means we can't do a simple compare for content equality
    }
    return null;
  }

  public File getFile() {
    return this.file;
  }

  public int getVersion() {
    return JarDeployer.extractVersionFromFilename(this.file.getName());
  }

  /**
   * Writes the given jarBytes to versionedJarFile
   */
  public DeployedJar(File versionedJarFile) {
    String artifactId = JarDeployer.toArtifactId(versionedJarFile.getName());

    this.file = versionedJarFile;
    this.artifactId = artifactId;

    if (!hasValidJarContent(versionedJarFile)) {
      throw new IllegalArgumentException(
          "File does not contain valid JAR content: " + versionedJarFile.getAbsolutePath());
    }

    byte[] digest = null;
    try {
      if (messageDigest != null) {
        digest = fileDigest(this.file);
      }
    } catch (IOException e) {
      // Ignored
    }
    this.md5hash = digest;
  }

  /**
   * Peek into the JAR data and make sure that it is valid JAR content.
   *
   * @param jarFile Jar containing data to be validated.
   * @return True if the data has JAR content, false otherwise
   */
  public static boolean hasValidJarContent(File jarFile) {
    boolean valid = false;

    try (FileInputStream fileInputStream = new FileInputStream(jarFile);
        JarInputStream jarInputStream = new JarInputStream(fileInputStream)) {
      valid = jarInputStream.getNextJarEntry() != null;
    } catch (IOException ignore) {
      // Ignore this exception and just return false
    }

    return valid;
  }

  /**
   * Scan the JAR file and attempt to register any function classes found.
   */

  public synchronized void registerFunctions() throws ClassNotFoundException {
    final boolean isDebugEnabled = logger.isDebugEnabled();
    if (isDebugEnabled) {
      logger.debug("Registering functions with DeployedJar: {}", this);
    }

    BufferedInputStream bufferedInputStream;
    try {
      bufferedInputStream = new BufferedInputStream(new FileInputStream(this.file));
    } catch (Exception ex) {
      logger.error("Unable to scan jar file for functions");
      return;
    }

    JarInputStream jarInputStream = null;
    try {
      Collection<String> functionClasses = findFunctionsInThisJar();
      jarInputStream = new JarInputStream(bufferedInputStream);
      JarEntry jarEntry = jarInputStream.getNextJarEntry();

      while (jarEntry != null) {
        if (jarEntry.getName().endsWith(".class")) {
          final String className = PATTERN_SLASH.matcher(jarEntry.getName()).replaceAll("\\.")
              .substring(0, jarEntry.getName().length() - 6);

          if (functionClasses.contains(className)) {
            if (isDebugEnabled) {
              logger.debug("Attempting to load class: {}, from JAR file: {}", jarEntry.getName(),
                  this.file.getAbsolutePath());
            }
            try {
              Class<?> clazz = ClassPathLoader.getLatest().forName(className);
              Collection<Function> registerableFunctions = getRegisterableFunctionsFromClass(clazz);
              for (Function function : registerableFunctions) {
                FunctionService.registerFunction(function);
                if (isDebugEnabled) {
                  logger.debug("Registering function class: {}, from JAR file: {}", className,
                      this.file.getAbsolutePath());
                }
                this.registeredFunctions.add(function);
              }
            } catch (ClassNotFoundException | NoClassDefFoundError cnfex) {
              logger.error("Unable to load all classes from JAR file: {}",
                  this.file.getAbsolutePath(), cnfex);
              throw cnfex;
            }
          } else {
            if (isDebugEnabled) {
              logger.debug("No functions found in class: {}, from JAR file: {}", jarEntry.getName(),
                  this.file.getAbsolutePath());
            }
          }
        }
        jarEntry = jarInputStream.getNextJarEntry();
      }
    } catch (IOException ioex) {
      logger.error("Exception when trying to read class from ByteArrayInputStream", ioex);
    } finally {
      if (jarInputStream != null) {
        try {
          jarInputStream.close();
        } catch (IOException ioex) {
          logger.error("Exception attempting to close JAR input stream", ioex);
        }
      }
      try {
        bufferedInputStream.close();
      } catch (IOException ignore) {
      }
    }
  }

  /**
   * Unregisters all functions from this jar if it was undeployed (i.e. newVersion == null), or all
   * functions not present in the new version if it was redeployed.
   *
   * @param newVersion The new version of this jar that was deployed, or null if this jar was
   *        undeployed.
   */
  protected synchronized void cleanUp(DeployedJar newVersion) {
    Stream<String> oldFunctions = this.registeredFunctions.stream().map(Function::getId);

    Stream<String> removedFunctions;
    if (newVersion == null) {
      removedFunctions = oldFunctions;
    } else {
      Predicate<String> isRemoved =
          (String oldFunctionId) -> !newVersion.hasFunctionWithId(oldFunctionId);

      removedFunctions = oldFunctions.filter(isRemoved);
    }

    removedFunctions.forEach(FunctionService::unregisterFunction);
    this.registeredFunctions.clear();
    try {
      TypeRegistry typeRegistry = ((InternalCache) CacheFactory.getAnyInstance()).getPdxRegistry();
      if (typeRegistry != null) {
        typeRegistry.flushCache();
      }
    } catch (CacheClosedException ignored) {
      // That's okay, it just means there was nothing to flush to begin with
    }
  }

  /**
   * Uses MD5 hashes to determine if the original byte content of this DeployedJar is the same as
   * that past in.
   *
   * @param stagedFile File to compare the original content to
   * @return True of the MD5 hash is the same o
   */
  boolean hasSameContentAs(final File stagedFile) {
    // If the MD5 hash can't be calculated then silently return no match
    if (messageDigest == null || this.md5hash == null) {
      return false;
    }

    byte[] compareToMd5;
    try {
      compareToMd5 = fileDigest(stagedFile);
    } catch (IOException ex) {
      return false;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("For JAR file: {}, Comparing MD5 hash {} to {}", this.file.getAbsolutePath(),
          new String(this.md5hash), new String(compareToMd5));
    }
    return Arrays.equals(this.md5hash, compareToMd5);
  }

  private byte[] fileDigest(File file) throws IOException {
    BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));
    try {
      byte[] data = new byte[8192];
      int read;
      while ((read = fis.read(data)) > 0) {
        messageDigest.update(data, 0, read);
      }
    } finally {
      fis.close();
    }

    return messageDigest.digest();
  }

  /**
   * Check to see if the class implements the Function interface. If so, it will be registered with
   * FunctionService. Also, if the functions's class was originally declared in a cache.xml file
   * then any properties specified at that time will be reused when re-registering the function.
   *
   * @param clazz Class to check for implementation of the Function class
   * @return A collection of Objects that implement the Function interface.
   */
  private Collection<Function> getRegisterableFunctionsFromClass(Class<?> clazz) {
    final List<Function> registerableFunctions = new ArrayList<>();

    try {
      if (Function.class.isAssignableFrom(clazz) && !Modifier.isAbstract(clazz.getModifiers())) {
        boolean registerUninitializedFunction = true;
        if (Declarable.class.isAssignableFrom(clazz)) {
          try {
            InternalCache cache = (InternalCache) CacheFactory.getAnyInstance();
            final List<Properties> propertiesList = cache.getDeclarableProperties(clazz.getName());

            if (!propertiesList.isEmpty()) {
              registerUninitializedFunction = false;
              // It's possible that the same function was declared multiple times in cache.xml
              // with different properties. So, register the function using each set of
              // properties.
              for (Properties properties : propertiesList) {
                @SuppressWarnings("unchecked")
                Function function = newFunction((Class<Function>) clazz, true);
                if (function != null) {
                  ((Declarable) function).initialize(cache, properties);
                  ((Declarable) function).init(properties); // for backwards compatibility
                  if (function.getId() != null) {
                    registerableFunctions.add(function);
                  }
                }
              }
            }
          } catch (CacheClosedException ignored) {
            // That's okay, it just means there were no properties to init the function with
          }
        }

        if (registerUninitializedFunction) {
          @SuppressWarnings("unchecked")
          Function function = newFunction((Class<Function>) clazz, false);
          if (function != null && function.getId() != null) {
            registerableFunctions.add(function);
          }
        }
      }
    } catch (Exception ex) {
      logger.error("Attempting to register function from JAR file: {}", this.file.getAbsolutePath(),
          ex);
    }

    return registerableFunctions;
  }

  protected Collection<String> findFunctionsInThisJar() throws IOException {
    return new FunctionScanner().findFunctionsInJar(this.file);
  }


  private Function newFunction(final Class<Function> clazz, final boolean errorOnNoSuchMethod) {
    try {
      final Constructor<Function> constructor = clazz.getConstructor();
      return constructor.newInstance();
    } catch (NoSuchMethodException nsmex) {
      if (errorOnNoSuchMethod) {
        logger.error("Zero-arg constructor is required, but not found for class: {}",
            clazz.getName(), nsmex);
      } else {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Not registering function because it doesn't have a zero-arg constructor: {}",
              clazz.getName());
        }
      }
    } catch (Exception ex) {
      logger.error("Error when attempting constructor for function for class: {}", clazz.getName(),
          ex);
    }

    return null;
  }

  /**
   * Get this jar's artifact ID, which is the part of the jar file name that precedes the version
   * information.
   *
   * @return the artifact ID for this jar
   */
  public String getArtifactId() {
    return this.artifactId;
  }

  /**
   * @return the filename as user deployed, i.e remove the sequence number
   */
  public String getDeployedFileName() {
    String fileBaseName = JarDeployer.getDeployedFileBaseName(this.file.getName());
    if (fileBaseName == null) {
      throw new IllegalStateException("file name needs to have a sequence number");
    }
    return fileBaseName + ".jar";
  }

  public String getFileCanonicalPath() throws IOException {
    return this.file.getCanonicalPath();
  }

  public URL getFileURL() {
    try {
      return this.file.toURL();
    } catch (MalformedURLException e) {
      logger.warn(e);
    }
    return null;
  }

  private boolean hasFunctionWithId(String id) {
    if (CollectionUtils.isEmpty(this.registeredFunctions)) {
      return false;
    }

    return this.registeredFunctions.stream().map(Function::getId)
        .anyMatch(functionId -> functionId.equals(id));
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (this.artifactId == null ? 0 : this.artifactId.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    DeployedJar other = (DeployedJar) obj;
    if (this.artifactId == null) {
      if (other.artifactId != null) {
        return false;
      }
    } else if (!this.artifactId.equals(other.artifactId)) {
      return false;
    }
    return true;
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder(getClass().getName());
    sb.append('@').append(System.identityHashCode(this)).append('{');
    sb.append("artifactId=").append(this.artifactId);
    sb.append(",file=").append(this.file.getAbsolutePath());
    sb.append(",md5hash=").append(toHex(this.md5hash));
    sb.append(",version=").append(this.getVersion());
    sb.append('}');
    return sb.toString();
  }

  private String toHex(byte[] data) {
    StringBuilder result = new StringBuilder();
    for (byte b : data) {
      result.append(String.format("%02x", b));
    }
    return result.toString();
  }
}
