package org.apache.maven.surefire.booter;

/*
 * 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.maven.surefire.api.util.ReflectionUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Properties;
import java.util.StringTokenizer;

import static java.lang.Character.isDigit;
import static java.lang.Thread.currentThread;
import static java.util.Objects.requireNonNull;
import static org.apache.maven.surefire.shared.lang3.StringUtils.isNumeric;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_FREE_BSD;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_LINUX;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_NET_BSD;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_OPEN_BSD;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodChain;
import static org.apache.maven.surefire.api.util.ReflectionUtils.tryLoadClass;

/**
 * JDK 9 support.
 *
 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
 * @since 2.20.1
 */
public final class SystemUtils
{
    public static final BigDecimal JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion();

    private static final BigDecimal JIGSAW_JAVA_VERSION = new BigDecimal( 9 ).stripTrailingZeros();

    private static final int PROC_STATUS_PID_FIRST_CHARS = 20;

    private SystemUtils()
    {
        throw new IllegalStateException( "no instantiable constructor" );
    }

    /**
     * @param jvmExecPath    e.g. /jdk/bin/java, /jdk/jre/bin/java
     * @return {@code true} if {@code jvmExecPath} is path to java binary executor
     */
    public static boolean endsWithJavaPath( String jvmExecPath )
    {
        File javaExec = new File( jvmExecPath ).getAbsoluteFile();
        File bin = javaExec.getParentFile();
        String exec = javaExec.getName();
        return exec.startsWith( "java" ) && bin != null && bin.getName().equals( "bin" );
    }

    /**
     * If {@code jvmExecutable} is <tt>/jdk/bin/java</tt> (since jdk9) or <tt>/jdk/jre/bin/java</tt> (prior to jdk9)
     * then the absolute path to JDK home is returned <tt>/jdk</tt>.
     * <br>
     * Null is returned if {@code jvmExecutable} is incorrect.
     *
     * @param jvmExecutable    /jdk/bin/java* or /jdk/jre/bin/java*
     * @return path to jdk directory; or <tt>null</tt> if wrong path or directory layout of JDK installation.
     */
    public static File toJdkHomeFromJvmExec( String jvmExecutable )
    {
        File bin = new File( jvmExecutable ).getAbsoluteFile().getParentFile();
        if ( "bin".equals( bin.getName() ) )
        {
            File parent = bin.getParentFile();
            if ( "jre".equals( parent.getName() ) )
            {
                File jdk = parent.getParentFile();
                return new File( jdk, "bin" ).isDirectory() ? jdk : null;
            }
            return parent;
        }
        return null;
    }

    /**
     * If system property <tt>java.home</tt> is <tt>/jdk</tt> (since jdk9) or <tt>/jdk/jre</tt> (prior to jdk9) then
     * the absolute path to
     * JDK home is returned <tt>/jdk</tt>.
     *
     * @return path to JDK
     */
    public static File toJdkHomeFromJre()
    {
        return toJdkHomeFromJre( System.getProperty( "java.home" ) );
    }

    /**
     * If {@code jreHome} is <tt>/jdk</tt> (since jdk9) or <tt>/jdk/jre</tt> (prior to jdk9) then
     * the absolute path to JDK home is returned <tt>/jdk</tt>.
     * <br>
     * JRE home directory {@code jreHome} must be taken from system property <tt>java.home</tt>.
     *
     * @param jreHome    path to /jdk or /jdk/jre
     * @return path to JDK
     */
    static File toJdkHomeFromJre( String jreHome )
    {
        File pathToJreOrJdk = new File( jreHome ).getAbsoluteFile();
        return "jre".equals( pathToJreOrJdk.getName() ) ? pathToJreOrJdk.getParentFile() : pathToJreOrJdk;
    }

    public static BigDecimal toJdkVersionFromReleaseFile( File jdkHome )
    {
        File release = new File( requireNonNull( jdkHome ).getAbsoluteFile(), "release" );
        if ( !release.isFile() )
        {
            return null;
        }
        Properties properties = new Properties();
        try ( InputStream is = new FileInputStream( release ) )
        {
            properties.load( is );
            String javaVersion = properties.getProperty( "JAVA_VERSION" ).replace( "\"", "" );
            StringTokenizer versions = new StringTokenizer( javaVersion, "._" );

            if ( versions.countTokens() == 1 )
            {
                javaVersion = versions.nextToken();
            }
            else if ( versions.countTokens() >= 2 )
            {
                String majorVersion = versions.nextToken();
                String minorVersion = versions.nextToken();
                javaVersion = isNumeric( minorVersion ) ? majorVersion + "." + minorVersion : majorVersion;
            }
            else
            {
                return null;
            }

            return new BigDecimal( javaVersion );
        }
        catch ( IOException e )
        {
            return null;
        }
    }

    /**
     * Safely extracts major and minor version as fractional number from
     * <pre>
     *     $MAJOR.$MINOR.$SECURITY
     * </pre>.
     * <br>
     *     The security version is usually not needed to know.
     *     It can be applied to not certified JRE.
     *
     * @return major.minor version derived from java specification version of <em>this</em> JVM, e.g. 1.8, 9, etc.
     */
    private static BigDecimal getJavaSpecificationVersion()
    {
        StringBuilder fractionalVersion = new StringBuilder( "0" );
        for ( char c : org.apache.maven.surefire.shared.lang3.SystemUtils.JAVA_SPECIFICATION_VERSION.toCharArray() )
        {
            if ( isDigit( c ) )
            {
                fractionalVersion.append( c );
            }
            else if ( c == '.' )
            {
                if ( fractionalVersion.indexOf( "." ) == -1 )
                {
                    fractionalVersion.append( '.' );
                }
                else
                {
                    break;
                }
            }
        }
        String majorMinorVersion = fractionalVersion.toString();
        return new BigDecimal( majorMinorVersion.endsWith( "." ) ? majorMinorVersion + "0" : majorMinorVersion )
                .stripTrailingZeros();
    }

    public static boolean isJava9AtLeast( String jvmExecutablePath )
    {
        File externalJavaHome = toJdkHomeFromJvmExec( jvmExecutablePath );
        File thisJavaHome = toJdkHomeFromJre();
        if ( thisJavaHome.equals( externalJavaHome ) )
        {
            return isBuiltInJava9AtLeast();
        }
        else
        {
            BigDecimal releaseFileVersion =
                    externalJavaHome == null ? null : toJdkVersionFromReleaseFile( externalJavaHome );
            return isJava9AtLeast( releaseFileVersion );
        }
    }

    public static boolean isBuiltInJava9AtLeast()
    {
        return JAVA_SPECIFICATION_VERSION.compareTo( JIGSAW_JAVA_VERSION ) >= 0;
    }

    public static boolean isJava9AtLeast( BigDecimal version )
    {
        return version != null && version.compareTo( JIGSAW_JAVA_VERSION ) >= 0;
    }

    public static ClassLoader platformClassLoader()
    {
        if ( isBuiltInJava9AtLeast() )
        {
            return reflectClassLoader( ClassLoader.class, "getPlatformClassLoader" );
        }
        return null;
    }

    public static Long pid()
    {
        if ( isBuiltInJava9AtLeast() )
        {
            Long pid = pidOnJava9();
            if ( pid != null )
            {
                return pid;
            }
        }

        if ( IS_OS_LINUX )
        {
            try
            {
                return pidStatusOnLinux();
            }
            catch ( Exception e )
            {
                // examine PID via JMX
            }
        }
        else if ( IS_OS_FREE_BSD || IS_OS_NET_BSD || IS_OS_OPEN_BSD )
        {
            try
            {
                return pidStatusOnBSD();
            }
            catch ( Exception e )
            {
                // examine PID via JMX
            }
        }

        return pidOnJMX();
    }

    static Long pidOnJMX()
    {
        String processName = ManagementFactory.getRuntimeMXBean().getName();
        if ( processName.contains( "@" ) )
        {
            String pid = processName.substring( 0, processName.indexOf( '@' ) ).trim();
            try
            {
                return Long.parseLong( pid );
            }
            catch ( NumberFormatException e )
            {
                return null;
            }
        }

        return null;
    }

    /**
     * $ cat /proc/self/stat
     * <br>
     * 48982 (cat) R 9744 48982 9744 34818 48982 8192 185 0 0 0 0 0 0 0 20 0 1 0
     * 137436614 103354368 134 18446744073709551615 4194304 4235780 140737488346592
     * 140737488343784 252896458544 0 0 0 0 0 0 0 17 2 0 0 0 0 0
     * <br>
     * $ SELF_PID=$(cat /proc/self/stat)
     * <br>
     * $ echo $CPU_ID | gawk '{print $1}'
     * <br>
     * 48982
     *
     * @return self PID
     * @throws Exception i/o and number format exc
     */
    static Long pidStatusOnLinux() throws Exception
    {
        return pidStatusOnLinux( "" );
    }

    /**
     * For testing purposes only.
     *
     * @param root    shifted to test-classes
     * @return same as in {@link #pidStatusOnLinux()}
     * @throws Exception same as in {@link #pidStatusOnLinux()}
     */
    static Long pidStatusOnLinux( String root ) throws Exception
    {
        try ( FileReader input = new FileReader( root + "/proc/self/stat" ) )
        {
            // Reading and encoding 20 characters is bit faster than whole line.
            // size of (long) = 19, + 1 space
            char[] buffer = new char[PROC_STATUS_PID_FIRST_CHARS];
            String startLine = new String( buffer, 0, input.read( buffer ) );
            return Long.parseLong( startLine.substring( 0, startLine.indexOf( ' ' ) ) );
        }
    }

    /**
     * The process status.  This file is read-only and returns a single
     * line containing multiple space-separated fields.
     * <br>
     * See <a href="https://www.freebsd.org/cgi/man.cgi?query=procfs&sektion=5">procfs status</a>
     * <br>
     * # cat /proc/curproc/status
     * <br>
     * cat 60424 60386 60424 60386 5,0 ctty 972854153,236415 0,0 0,1043 nochan 0 0 0,0 prisoner
     * <br>
     * Fields are:
     * <br>
     * comm pid ppid pgid sid maj, min ctty, sldr start user/system time wmsg euid ruid rgid,egid,
     * groups[1 .. NGROUPS] hostname
     *
     * @return current PID
     * @throws Exception if could not read /proc/curproc/status
     */
    static Long pidStatusOnBSD() throws Exception
    {
        return pidStatusOnBSD( "" );
    }

    /**
     * For testing purposes only.
     *
     * @param root    shifted to test-classes
     * @return same as in {@link #pidStatusOnBSD()}
     * @throws Exception same as in {@link #pidStatusOnBSD()}
     */
    static Long pidStatusOnBSD( String root ) throws Exception
    {
        try ( BufferedReader input = new BufferedReader( new FileReader( root + "/proc/curproc/status" ) ) )
        {
            String line = input.readLine();
            int i1 = 1 + line.indexOf( ' ' );
            int i2 = line.indexOf( ' ', i1 );
            return Long.parseLong( line.substring( i1, i2 ) );
        }
    }

    static Long pidOnJava9()
    {
        ClassLoader classLoader = currentThread().getContextClassLoader();
        Class<?> processHandle = tryLoadClass( classLoader, "java.lang.ProcessHandle" );
        Class<?>[] classesChain = { processHandle, processHandle };
        String[] methodChain = { "current", "pid" };
        return (Long) invokeMethodChain( classesChain, methodChain, null );
    }

    static ClassLoader reflectClassLoader( Class<?> target, String getterMethodName )
    {
        try
        {
            Method getter = ReflectionUtils.getMethod( target, getterMethodName );
            return (ClassLoader) ReflectionUtils.invokeMethodWithArray( null, getter );
        }
        catch ( RuntimeException e )
        {
            return null;
        }
    }
}
