All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nerdvision.agent.ClientReg Maven / Gradle / Ivy

package com.nerdvision.agent;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.jar.Attributes;
import java.util.regex.Pattern;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ClientReg
{
    private static final Logger LOGGER = LoggerFactory.getLogger( ClientReg.class );

    private final Pattern envKeyFilter;
    private final Pattern javaFilter;
    private final int maxStringLength;
    private final String apikey;
    private final String licenseUrl;
    private final Long backoffMax;
    private final double maxMultiplier;
    private final Settings settings;
    private final Attributes manifest;
    private final String jarPath;
    private final String uuid;
    private final HTTPClient httpClient;
    private final String nvStartMode;

    private String sessionId;


    public ClientReg( final Settings settings,
                      final Attributes manifest,
                      final String jarPath,
                      final String uuid,
                      final HTTPClient httpClient )
    {
        envKeyFilter = settings.getSettingAs( "env.regex", Pattern.class );
        javaFilter = settings.getSettingAs( "java.regex", Pattern.class );
        maxStringLength = settings.getSettingAs( "env.max.str.length", int.class );
        apikey = settings.getSettingAs( "apikey", String.class );
        licenseUrl = settings.getLicenseUrl();
        backoffMax = settings.getSettingAs( "client.registration.backoff.max", long.class );
        maxMultiplier = settings.getSettingAs( "client.registration.backoff.multiplier", double.class );
        nvStartMode = settings.getSettingAs( "nv.start_method", String.class );
        this.settings = settings;
        this.manifest = manifest;
        this.jarPath = jarPath;
        this.uuid = uuid;
        this.httpClient = httpClient;
    }


    public String getSession()
    {
        final long start = System.currentTimeMillis();

        int cnt = 0;
        while( sessionId == null )
        {
            cnt++;
            final Map data = buildClientRegDocument( start );

            LOGGER.debug( "Sending client registration to ({}): {}", this.licenseUrl, data );
            final byte[] bytes = JsonUtils.toJson( data );
            final JSONObject res = httpClient.postJson( licenseUrl, bytes,
                    new HTTPClient.JsonBodyHandler(  ) );
            if( res != null )
            {
                this.sessionId = res.getString( "session" );
                httpClient.setSession( sessionId );
            }
            else
            {
                long delay = backoff( cnt, backoffMax, maxMultiplier );
                if( delay > 0 )
                {
                    synchronized( this )
                    {
                        try
                        {
                            wait( delay * 1000 );
                        }
                        catch( InterruptedException e )
                        {
                            LOGGER.debug( "Interrupted during wait." );
                        }
                    }
                }
            }
        }
        return sessionId;
    }


    public Map buildClientRegDocument( final long start )
    {
        final Map data = new HashMap<>();
        data.put( "uid", this.uuid );
        data.put( "api_key", apikey );
        data.put( "instance", new HashMap()
        {{
            put( "name", settings.getSettingAs( "name", String.class ) );
            put( "start_ts", String.valueOf( start ) );
            put( "start_mode", nvStartMode );
        }} );
        data.put( "network", getNetworkData() );
        data.put( "language", getLanguageData() );
        data.put( "env", getEnvData() );
        data.put( "os", getOSData() );
        data.put( "product", getProductData() );
        data.put( "tags", settings.getSettingAs( "tags", Map.class ) );
        return data;
    }


    public Map getProductData()
    {
        final Map data = new HashMap<>();
        data.put( "build", manifest.getValue( "Implementation-Build" ) );
        data.put( "version", manifest.getValue( "Version" ) );

        data.put( "major_version", manifest.getValue( "Version-Major" ) );
        data.put( "minor_version", manifest.getValue( "Version-Minor" ) );
        data.put( "micro_version", manifest.getValue( "Version-Micro" ) );

        data.put( "name", "nerdvision Java - Agent" );
        data.put( "path", jarPath );

        return data;
    }


    public Map getOSData()
    {
        final Map osMap = new HashMap<>();

        osMap.put( "name", System.getProperty( "os.name" ) );
        osMap.put( "version", System.getProperty( "os.version" ) );
        osMap.put( "arch", System.getProperty( "os.arch" ) );

        osMap.put( "lang", Locale.getDefault().getLanguage() );
        osMap.put( "locale", Locale.getDefault().getCountry() );
        osMap.put( "timezone", TimeZone.getDefault().getID() );

        osMap.put( "time", System.currentTimeMillis() );

        return osMap;
    }


    public Map getNetworkData()
    {
        final Map data = new HashMap<>();
        try
        {
            final InetAddress local = InetAddress.getLocalHost();
            data.put( "hostname", local.getHostName() );

            final String hostAddress = local.getHostAddress();
            data.put( "address", hostAddress );
        }
        catch( final UnknownHostException ex )
        {
            LOGGER.debug( "Exception getting host name." );
        }
        return data;
    }


    private Map getLanguageData()
    {
        final Map data = new HashMap<>();
        data.put( "type", "java" );
        data.put( "version", System.getProperty( "java.runtime.version" ) );
        data.put( "name", System.getProperty( "java.runtime.name" ) );

        final Map properties = new HashMap<>();
        data.put( "properties", properties );

        final Properties props = System.getProperties();
        final Set keys = props.stringPropertyNames();
        for( final String key : keys )
        {
            final String value = props.getProperty( key );

            if( key.startsWith( "java." ) || key.startsWith( "sun." ) )
            {
                final String k = trimString( key.replace( '.', '_' ) );
                properties.put( k, value );
            }
        }

        try
        {
            final List args = new ArrayList<>();
            final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            for( final String arg : runtimeMXBean.getInputArguments() )
            {
                if( javaFilter == null || !javaFilter.matcher( arg ).matches() )
                {
                    args.add( arg );
                }
            }

            data.put( "args", args );
        }
        catch( Throwable ignored )
        {
        }

        return data;
    }


    public static long backoff( final int attempt, final long maxDelayInSeconds, final double multiplier )
    {
        final double delayInSec = (Math.pow( 2.0, attempt ) - 1.0) * .5;
        return Math.round( Math.min( delayInSec * multiplier, maxDelayInSeconds ) );
    }


    public Map getEnvData()
    {
        final Map rtn = new HashMap<>();
        try
        {
            final Map env = System.getenv();
            for( final String key : env.keySet() )
            {
                boolean filter = false;
                if( envKeyFilter != null && envKeyFilter.matcher( key ).matches() )
                {
                    filter = true;
                }
                if( !filter )
                {
                    final String value = trimString( env.get( key ) );
                    rtn.put( key, value );
                }
            }
        }
        catch( SecurityException se )
        {
            LOGGER.debug( "Cannot process ENV", se );
        }
        return rtn;
    }


    private String trimString( final String s )
    {
        if( s.length() > this.maxStringLength )
        {
            return s.substring( 0, this.maxStringLength );
        }
        return s;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy