/*
 * 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.internal.logging.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 jarName;
  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, final String jarName) {
    Assert.assertTrue(jarName != null, "jarName cannot be null");
    Assert.assertTrue(versionedJarFile != null, "versionedJarFile cannot be null");

    this.file = versionedJarFile;
    this.jarName = jarName;

    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) {
    JarInputStream jarInputStream = null;
    boolean valid = false;

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

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

  /**
   * 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;
  }

  /**
   * @return the unversioned name of this jar file, e.g. myJar.jar
   */
  public String getJarName() {
    return this.jarName;
  }

  public String getFileName() {
    return this.file.getName();
  }

  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.jarName == null ? 0 : this.jarName.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.jarName == null) {
      if (other.jarName != null) {
        return false;
      }
    } else if (!this.jarName.equals(other.jarName)) {
      return false;
    }
    return true;
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder(getClass().getName());
    sb.append('@').append(System.identityHashCode(this)).append('{');
    sb.append("jarName=").append(this.jarName);
    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();
  }
}
