/*
 * 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.
 */

import org.apache.tools.ant.BuildException

// Checks logging calls to keep from using patterns that might be expensive
// either in CPU or unnecessary object creation. Some of the checks are a little
// over-zealous, but it's worth a bit of aggravation to catch the egregious
// mistakes before they accrue.

// This all started with Java Flight Recorder showing a massive number of
// objects allocated and garbage collected. Tracing a bunch of them down showed
// that we have a number of calls like:
// log.debug("some string" + very_expensive_object_to_make_a_string).
// which _always_ constructed the very expensive ojbect even if the log level
// was INFO or more severe. Rather than leave lots of confusing formats laying
// about or expecting people to remember the rules, we opted to make this
// check part of Gradle precommit. It will be included by default in Solr
// 9.0.

// See the associated help task "gradlew helpValidateLogCalls"

configure(subprojects.findAll { it.path.startsWith(':solr') }) {
  plugins.withType(JavaPlugin) {
    task validateLogCalls(type: ValidateLogCallsTask) { task ->
      description "Checks that log calls are either validated or conform to efficient patterns."
      group "verification"

      sourceFiles = files(sourceSets*.java)
    }
 
    // Add log validation to per-project checks as well.
    check.dependsOn validateLogCalls
 }
}

class ValidateLogCallsTask extends DefaultTask {
  @Input
  def logLevels = ["log.trace", "log.debug", "log.info", "log.warn", "log.error", "log.fatal"]

  private def errsFound = 0;
  private def violations = new ArrayList();

  def reportViolation(String msg) {
    violations.add(System.lineSeparator + msg);
    errsFound++;
  }

  // We have a log.something line, check for patterns we're not fond of.
  def checkLine(File file, String line, int lineNumber, String previous) {
    boolean violation = false

    // If the line has been explicitly OK'd, then it's OK!
    if (line.replaceAll("\\s", "").toLowerCase().contains("//nowarn")) {
      return
    }
    // Strip all of the comments, things in quotes and the like.
    def stripped =
        line.replaceFirst("//.*", " ") // remove comment to EOL. May be fragile due to the possibility of embedded double slashes
            .replaceFirst(/.*?\(/, " ") // Get rid of "log.whatever("
            .replaceFirst(/\);/, " ") // get rid of the closing ");"
            .replaceFirst("/\\*.*?\\*/", " ") // replace embedded comments "/*....*/"
            .replaceAll(/".*?"/, '""') // remove anything between quotes. This is a bit fragile if there are embedded double quotes.
            .replaceAll(/timeLeft\(.*?\)/, " ") // used all over tests, it's benign
            .replaceAll(/TimeUnit\..*?\.convert\(.*?\)/, " ") // again, a pattern that's efficient
            .replaceAll("\\s", "")

    // The compiler will pre-assemble patterns like 'log.info("string const1 {}" + " string const2 {}", obj1, obj2)'
    // to log.info("string const1 {} string const2 {}", obj1, obj2)', so don't worry about any plus preceded and
    // followed by double quotes, otherwise flag it.
    def hasPlus = false
    for (int idx = 0; idx < stripped.length(); ++idx) {
      if (stripped.charAt(idx) == '+') {
        if (idx == 0 || idx == stripped.length() - 1
            || stripped.charAt(idx - 1) != '"' || stripped.charAt(idx + 1) != '"') {
          hasPlus = true
          break
        }
      }
    }
    //TODO remove me
    String cause =  ""
    // Get the level of this log message.
    // We don't really care about checking for method calls for WARN and more severe, the presumption
    // is that they _should_ always be reported.

    def level = ""
    def lev = (line =~ "log\\.(.*?)\\(")
    if (lev.find()) {
      level = lev.group(1).toLowerCase().trim()
    }
    if (logLevels.contains("log." + level) == false) {
      reportViolation(String.format("Found an unexpected log level: %s, file: %s:%d"
          , level, file.getAbsolutePath(), lineNumber))
    }
    boolean persnicketyLevel = !(level.equals("fatal") || level.equals("error") || level.equals("warn"))

    // Check that previous line isn't an if statement for always-reported log levels.
    // There's a convention to declare a member variable for whether a level is enabled and check that rather than
    // isDebugEnabled so we need to check both.
    String prevLine = previous.replaceAll("\\s+", "").toLowerCase()
    boolean prevLineNotIf = ((prevLine.contains("if(log.is" + level + "enabled") == false
        && prevLine.contains("if(" + level + ")") == false))

    if (hasPlus) {
      cause = "hasPlus: " + hasPlus
      violation = true
    }
    if (violation == false) {
      def m = stripped =~ "\\(.*?\\)"
      def hasParens = m.find()

      if (hasParens && prevLineNotIf && persnicketyLevel) {
        cause = "hasParens " + hasParens + " prevLineNotIf " + prevLineNotIf + " pernicketyLevel " + persnicketyLevel
        violation = true
      }
    }

    // Always report toString(). Note, this over-reports some constructs
    // but just add //nowarn if it's really OK.
    if (violation == false) {
      if (line.contains("toString(") == true && prevLineNotIf) {
        cause = "Line contains toString"
        violation = true
      }
    }
    if (stripped.contains("getMessage()") || stripped.contains("getCause()")) {
      cause = "getMessage or getCause in log line";
      violation = true;
    }
    if (violation) {
      reportViolation(String.format("cause: '%s' Suspicious logging call, Parameterize and possibly surround with 'if (log.is*Enabled) {..}'. Help at: 'gradlew helpValidateLogCalls' %s    %s:%d"
          , cause , System.lineSeparator, file.getAbsolutePath(), lineNumber))
    }
    return
  }

// Require all our logger definitions lower case "log", except if they have //nowarn
  def checkLogName(File file, String line) {
    // It's many times faster to do check this way than use a regex
    if (line.contains("static ") && line.contains("getLogger") && line.contains(" log ") == false) {
      if (line.replaceAll("\\s", "").toLowerCase().contains("//nowarn")) {
        return
      }
      reportViolation("Change the logger name to lower-case 'log' in " + file.name + " " + line + " project" + project)
    }
  }

  def checkFile(File file) {
    int state = 0
    int lineNumber = 0
    StringBuilder sb = new StringBuilder();

    // We have to assemble line-by-line to get the full log statement. We require that all loggers (except requestLog
    // and slowLog) be exactly "log". That will be checked as well.
    String prevLine = ""
    file.eachLine { String line ->
      lineNumber++
      checkLogName(file, line)
      switch (state) {
        case 0: // Not collecting a logging line.
          logLevels.each {
            if (line.contains(it)) {
              if (line.contains(");")) {
                state = 2
              } else {
                state = 1
              }
              sb.setLength(0)
              sb.append(line)
            }
          }
          break

        case 1: // collecting a log line
          if (line.replaceFirst("//.*", " ")
              .replaceFirst("/\\*.*?\\*/", " ") // replace embedded comments "/*....*/"
              .replaceAll(/".*?"/, '""') // remove anything between quotes. This is a bit fragile if there are embedded double quotes.
              .trim().endsWith(");")) {
            state = 2
          }
          sb.append(line)
          break

        default:
          reportViolation("Bad state, should be 0-1 in the switch statement") // make people aware the code sucks
          break
      }

      // It's just easier to do this here rather than read another line in the switch above.
      if (state == 0) {
          // Not collecting a log line
          prevLine = line.toLowerCase();
      } else if (state == 1) {
          // collecting a logging line.
      } else if (state == 2) {
          // We've collected the complete log line.
          checkLine(file, sb.toString(), lineNumber, prevLine)
          state = 0
      } else {
          assert false
      }
    }
  }

  @InputFiles
  @PathSensitive(PathSensitivity.RELATIVE)
  FileCollection sourceFiles

  @TaskAction
  def checkLogLines() {
    sourceFiles.each { checkFile(it) }
    logger.info("Checked: ${sourceFiles.files.size()}")

    if (errsFound > 0) {
      throw new BuildException(String.format(Locale.ENGLISH, 'Found %d violations in source files (%s).',
          errsFound, violations.join(', ')));
    }
  }
}
