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

log.com.unbound.common.Log Maven / Gradle / Ivy

Go to download

This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi

There is a newer version: 42761
Show newest version
package com.unbound.common;

import javax.crypto.ShortBufferException;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.nio.charset.StandardCharsets;
import java.time.*;
import java.util.HashMap;

public class Log
{

  private native static boolean jniEnabled();
  private native static long jniEnter(String name);
  private native static void jniEnterOut(long ctx);
  private native static void jniPrint(String label);
  private native static void jniLeave(int rv);
  private native static void jniDataInt(String name, long value, int flags);
  private native static void jniDataChars(String name, char[] value, int offset, int length);
  private native static void jniDataBytes(String name, byte[] value, int offset, int length);
  private native static void jniDataInts(String name, int[] value, int offset, int length);
  private native static void jniDataShorts(String name, short[] value, int offset, int length);
  private native static void jniDataLongs(String name, long[] value, int offset, int length);


  public static Log func(String name)
  {
    Log log = getInstance();
    log.beginFunc(name);
    return log;
  }

  public void failed(Exception e)
  {
    this.failed = e;
  }

  public Log leavePrint()
  {
    if (failed==null) return this;

    String message = failed.getMessage();
    if (message==null) message = failed.toString();

    log("Error", message);
    end();
    return disabled;
  }

  public void leave()
  {
    leavePrint().end();
  }

  public static Log print(String label)
  {
    Log log = getInstance();
    log.beginPrint(label);
    return log;
  }

  public Log log(String name, boolean value) { return logLong(name, value ? 1 : 0, false);  }
  public Log log(String name, Boolean value) { return value==null ? this : log(name, value.booleanValue());  }

  public Log log(String name, long value) {  return logLong(name, value, false); }
  public Log logHex(String name, long value) { return logLong(name, value, true); }

  public Log log(String name, Long value) { return value==null ? this : log(name, value.longValue());  }
  public Log logHex(String name, Long value) { return value==null ? this : log(name, value.longValue());  }

  public Log log(String name, int value) { return logLong(name, ((long)value) & 0xffffffffL, false);  }
  public Log logHex(String name, int value) {  return logLong(name, ((long)value) & 0xffffffffL, true); }

  public Log log(String name, Integer value) { return value==null ? this : log(name, value.intValue());  }
  public Log logHex(String name, Integer value) { return value==null ? this : log(name, value.intValue());  }

  public Log log(String name, short value) { return logLong(name, ((long)value) & 0xffff, false);   }
  public Log logHex(String name, short value) { return logLong(name, ((long)value) & 0xffff, true);  }

  public Log log(String name, Short value) { return value==null ? this : log(name, value.shortValue());  }
  public Log logHex(String name, Short value) { return value==null ? this : log(name, value.shortValue());  }

  public Log log(String name, byte value) { return logLong(name, ((long)value) & 0xff, false); }
  public Log logHex(String name, byte value) { return logLong(name, ((long)value) & 0xff, true);  }

  public Log log(String name, Byte value) { return value==null ? this : log(name, value.byteValue());  }
  public Log logHex(String name, Byte value) { return value==null ? this : log(name, value.byteValue());  }

  public Log log(String name, String value)
  {
    if (!enabled) return disabled;

    byte[] bytes = value==null ? null : value.getBytes(StandardCharsets.UTF_8);
    return logBytes(name, bytes, true);
  }

  public Log log(String name, byte[] value) { return logBytes(name, value, false); }
  public Log logLen(String name, byte[] value) { return value==null ? this : log(name, value.length); }

  //---------------------- implementation ----------------------
  private static final class DisabledLog extends Log
  {
    @Override public void failed(Exception e) { }
    @Override public Log log(String name, long value) { return this; }
    @Override public Log logHex(String name, long value)  { return this; }
    @Override public Log log(String name, int value)  { return this; }
    @Override public Log log(String name, boolean value)  { return this; }
    @Override public Log log(String name, short value)  { return this; }
    @Override public Log log(String name, byte value)  { return this; }
    @Override public Log logHex(String name, short value)  { return this; }
    @Override public Log logHex(String name, byte value)  { return this; }
    @Override public Log logHex(String name, int value)  { return this; }
    @Override public Log log(String name, byte[] value) { return this; }
    @Override public Log log(String name, short[] value) { return this; }
    @Override public Log log(String name, int[] value) { return this; }
    @Override public Log log(String name, char[] value) { return this; }
    @Override public Log log(String name, String value) { return this; }
    @Override protected void beginPrint(String label) {}
    @Override protected void beginFunc(String name) {}
    @Override public Log leavePrint() { return this; }
    @Override public Log end() { return this; }
  }

  //---------------------- implementation ----------------------
  private static final class NativeLog extends Log
  {
    private static final int HEX = 0x01000000;

    private Exception failed = null;
    private long context = 0;
    private String printLabel = null;

    @Override public void failed(Exception e) { failed = e; }
    @Override public Log log(String name, boolean value)  { Log.jniDataInt(name, value ? 1 : 0, 4);  return this; }
    @Override public Log log(String name, byte value)     { Log.jniDataInt(name, value, 1);  return this; }
    @Override public Log log(String name, short value)    { Log.jniDataInt(name, value, 2);  return this; }
    @Override public Log log(String name, int value)      { Log.jniDataInt(name, value, 4);  return this; }
    @Override public Log log(String name, long value)     { Log.jniDataInt(name, value, 8);  return this; }
    @Override public Log logHex(String name, byte value)  { Log.jniDataInt(name, value, 1|HEX);  return this; }
    @Override public Log logHex(String name, short value) { Log.jniDataInt(name, value, 2|HEX);  return this; }
    @Override public Log logHex(String name, int value)   { Log.jniDataInt(name, value, 4|HEX);  return this; }
    @Override public Log logHex(String name, long value)  { Log.jniDataInt(name, value, 8|HEX);  return this; }
    @Override public Log log(String name, byte[] value)   { Log.jniDataBytes (name, value, 0, value==null ? 0 : value.length);  return this; }
    @Override public Log log(String name, short[] value)  { Log.jniDataShorts(name, value, 0, value==null ? 0 : value.length);  return this; }
    @Override public Log log(String name, int[] value)    { Log.jniDataInts  (name, value, 0, value==null ? 0 : value.length);  return this; }
    @Override public Log log(String name, char[] value)   { Log.jniDataChars (name, value, 0, value==null ? 0 : value.length);  return this; }
    @Override public Log log(String name, String value)
    {
      char[] chars = value==null ? null : value.toCharArray();
      Log.jniDataChars(name, chars, 0, chars==null ? 0 : chars.length);
      return this;
    }
    @Override protected void beginPrint(String label) { printLabel = label; }
    @Override protected void beginFunc(String name) { context = Log.jniEnter(name); }

    // @Override public Log leavePrint() { return this; }

    @Override public Log end()
    {
      if (context!=0) { Log.jniEnterOut(context); context=0; }
      else if (printLabel!=null) { Log.jniPrint(printLabel); printLabel=null; }
      else
      {
        Log.jniLeave(Log.exceptionToRv(failed));
        failed = null;
      }
      return this;
    }
  }

  private static boolean enabled = false;
  private static Log disabled = new DisabledLog();
  private static final ThreadLocal thread = new ThreadLocal<>();
  private static Clock clock = Clock.systemUTC();

  private static final int DYLOG_SIGNATURE = 0X6E877B21;

  private static final int DYLOG_BLOCK_CONTROL = 0;
  private static final int DYLOG_BLOCK_ENTER = 1;
  private static final int DYLOG_BLOCK_LEAVE = 2;
  private static final int DYLOG_BLOCK_PRINT = 3;

  private static final int DYLOG_CTRL_STRING = 0;
  private static final int DYLOG_CTRL_LABEL  = 1;

  private static final int DYLOG_DEC   = 0;
  private static final int DYLOG_HEX   = 1;
  private static final int DYLOG_CHARS = 2;
  private static final int DYLOG_ARR_1 = 3;
  private static final int DYLOG_ARR_2 = 4;
  private static final int DYLOG_ARR_4 = 5;
  private static final int DYLOG_CHARS_ID = 6;

  private static String dir;
  private static long pid;
  private static boolean isNative = false;

  static
  {
    try
    {
      try
      {
        System.loadLibrary("dylog");
        isNative = true;
      }
      catch (Throwable e) {}

      if (isNative)
      {
        enabled = jniEnabled();
      }
      else
      {
        String e = System.getenv("DYLOG_ENABLED");
        enabled = (e==null) ? Config.getBool("log", "enabled") : e.equals("1");

        if (enabled)
        {
          RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();

          String root = Config.isWindows ? "C:\\Windows\\Temp" : "/tmp";
          dir = root + "/dy.log";
          new File(dir).mkdirs();

          // Get name representing the running Java virtual machine.
          // It returns something like 6460@AURORA. Where the value
          // before the @ symbol is the PID.
          String jvmName = runtime.getName();
          pid = Long.parseLong(jvmName.split("@")[0]);
        }
      }
    }
    catch (Exception e)
    {
      enabled = false;
    }
  }

  private FileOutputStream file;
  private long timerMs;
  private long timerMsDiff;
  private HashMap strings = new HashMap<>();
  private byte[] paramsBuf = new byte[64];
  private int paramsLength = 0;
  private int stringsCount = 0;
  private byte[] tempBuf = new byte[32];
  private int tempBufLength = 0;
  private int printId = 0;
  private int funcId = 0;
  private Exception failed = null;

  protected void init() throws Exception
  {
    if (isNative) return;

    String path = dir + "/java_P" + pid + "_T" + Thread.currentThread().getId() + ".dylog";
    file = new FileOutputStream(path);

    Instant now = Instant.now();
    ZoneOffset offset = ZoneOffset.systemDefault().getRules().getOffset(now);
    long localTimeMs = now.toEpochMilli() + offset.getTotalSeconds()*1000;

    timerMs = clock.millis();
    timerMsDiff = System.nanoTime() - timerMs*1000000;
    outLabel(localTimeMs);
  }

  private void setParamsCapacity(int capacity)
  {
    if (capacity<= paramsLength) return;
    if (capacity< paramsLength *2) capacity = paramsLength *2;
    byte[] newBuf = new byte[capacity];
    System.arraycopy(paramsBuf, 0, newBuf, 0, paramsLength);
    paramsBuf = newBuf;
  }

  private static int getValueLengthCode(int value)
  {
    if (value < 0) return 3;

    if (value==0x00000000) return 0;
    if (value<=0x000000ff) return 1;
    if (value<=0x0000ffff) return 2;
    return 3;
  }

  private void outByte(byte value)
  {
    tempBuf[tempBufLength++] = value;
  }

  private void outValue(int value)
  {
    if (value<0 || value>=65536) { outByte((byte)(value>>24)); outByte((byte)(value>>16)); }
    if (value<0 || value>=256) outByte((byte)(value>>8));
    if (value!=0) outByte((byte)value);
  }

  private void outBlockHeader(int code, int length, int id, int timer)
  {
    byte header = (byte)(
      (code                       << 6) |
      (getValueLengthCode(length)  << 4) |
      (getValueLengthCode(id)    << 2) |
       getValueLengthCode(timer));

    tempBufLength = 0;
    outByte(header);
    outValue(length);
    outValue(id);
    outValue(timer);
    out(tempBuf, tempBufLength);
  }

  private void out(byte[] in, int length)
  {
    try { file.write(in, 0, length); }
    catch (Exception e) { }
  }

  private void outLabel(long localTimeMs)
  {
    outBlockHeader(DYLOG_BLOCK_CONTROL, 8, DYLOG_CTRL_LABEL, DYLOG_SIGNATURE);
    Converter.setBE8(tempBuf, 0, localTimeMs); out(tempBuf, 8);
  }

  private void outString(String str)
  {
    byte[] data = str.getBytes(StandardCharsets.UTF_8);
    outBlockHeader(DYLOG_BLOCK_CONTROL, data.length, DYLOG_CTRL_STRING, 0);
    out(data, data.length);
  }

  private void outFuncEnter(long newTimerMs, int id)
  {
    outBlockHeader(DYLOG_BLOCK_ENTER, paramsLength, id, (int)(newTimerMs - timerMs));
    out(paramsBuf, paramsLength);
  }

  private void outFuncLeave(long newTimerMs, int rv)
  {
    outBlockHeader(DYLOG_BLOCK_LEAVE, paramsLength, rv, (int)(newTimerMs - timerMs));
    out(paramsBuf, paramsLength);
  }

  private void outPrint(long newTimerMs, int id)
  {
    outBlockHeader(DYLOG_BLOCK_PRINT, paramsLength, id, (int)(newTimerMs - timerMs));
    out(paramsBuf, paramsLength);
  }

  private int getStringId(String str)
  {
    Integer i = strings.get(str);
    if (i!=null) return i;
    stringsCount++;
    strings.put(str, stringsCount);
    outString(str);
    return stringsCount;
  }

  private void cleanParams() { paramsLength = 0; }

  private static Log getInstance()
  {
    if (!enabled) return disabled;
    Log log = thread.get();
    if (log == null)
    {
      if (isNative) log = new NativeLog();
      else
      {
        log = new Log();
        try {  log.init(); }
        catch (Exception e) { log = disabled; }
      }

      thread.set(log);
    }
    return log;
  }

  protected void beginFunc(String name)
  {
    funcId = getStringId(name);
  }

  protected void beginPrint(String label)
  {
    printId = getStringId(label);
  }

  public Log end()
  {
    long newTimerMs = (System.nanoTime()-timerMsDiff) / 1000000;
    if (funcId!=0)
    {
      outFuncEnter(newTimerMs, funcId);
      funcId = 0;
    }
    else if (printId!=0)
    {
      outPrint(newTimerMs, printId);
      printId = 0;
    }
    else
    {
      outFuncLeave(newTimerMs, exceptionToRv(failed));
    }
    failed = null;
    timerMs = newTimerMs;
    cleanParams();
    return this;
  }

//-------------------------------------- data -------------------------------------

  private int getParamLengthCode(int length)
  {
    if (length<=5) return length;
    if (length<=255) return 6;
    return 7;
  }

  private int getParamValueLength(long value)
  {
    int length = 0;
    while (value!=0)
    {
      length++;
      value>>>=8;
    }
    return length;
  }

  private void outParamValue(long value)
  {
    int length = 0;
    while (value!=0)
    {
      tempBuf[length++] = (byte)(value);
      value>>>=8;
    }
    while (length!=0) paramsBuf[paramsLength++] = tempBuf[--length];
  }

  private void outParamByte(byte value)
  {
    setParamsCapacity(paramsLength + 1);
    paramsBuf[paramsLength++] = value;
  }

  private void outParamHeader(int code, int length, int id)
  {
    int paramLengthCode = getParamLengthCode(length);
    int idLengthCode = getValueLengthCode(id);

    byte header =(byte)(
      (code << 5)            |
      (paramLengthCode << 2) |
       idLengthCode);
    outParamByte(header);
    if (length>5)
    {
      if (length>=0x000000ff) outParamByte((byte)(length>>8));
      outParamByte((byte)length);
    }
    if (id>0x0000ffff || id<0)
    {
      outParamByte((byte)(id>>24));
      outParamByte((byte)(length>>16));
    }
    if (id>0x000000ff) outParamByte((byte)(id>>8));
    if (id>0) outParamByte((byte)(id));
  }

  private Log logLong(String name, long value, boolean hex)
  {
    int id = getStringId(name);

    if (value==0) hex = false;
    int code = hex ? DYLOG_HEX : DYLOG_DEC;

    int outLength = getParamValueLength(value);
    outParamHeader(code, outLength, id);
    setParamsCapacity(paramsLength + outLength);
    outParamValue(value);

    return this;
  }

  private Log logBytes(String name, byte[] value, boolean chars)
  {
    if (value==null) return logLong(name, 0, false);

    int id = getStringId(name);
    int code = chars ? DYLOG_CHARS : DYLOG_ARR_1;

    outParamHeader(code, value.length, id);
    setParamsCapacity(paramsLength + value.length);
    System.arraycopy(value, 0, paramsBuf, paramsLength, value.length);
    paramsLength += value.length;
    return this;
  }

  public Log log(String name, short[] value)
  {
    if (value==null) return logLong(name, 0, false);

    int id = getStringId(name);
    outParamHeader(DYLOG_ARR_2, value.length*2, id);
    setParamsCapacity(paramsLength + value.length*2);
    for (short v : value)
    {
      paramsBuf[paramsLength++] = (byte)(v>>8);
      paramsBuf[paramsLength++] = (byte)v;
    }
    return this;
  }


  public Log log(String name, int[] value)
  {
    if (value==null) return logLong(name, 0, false);

    int id = getStringId(name);
    outParamHeader(DYLOG_ARR_4, value.length*4, id);
    setParamsCapacity(paramsLength + value.length*4);
    for (int v : value)
    {
      paramsBuf[paramsLength++] = (byte)(v>>24);
      paramsBuf[paramsLength++] = (byte)(v>>16);
      paramsBuf[paramsLength++] = (byte)(v>>8);
      paramsBuf[paramsLength++] = (byte)v;
    }
    return this;
  }

  public Log log(String name, char[] value)
  {
    if (value==null) return logLong(name, 0, false);

    int id = getStringId(name);
    outParamHeader(DYLOG_CHARS, value.length, id);
    setParamsCapacity(paramsLength + value.length);
    for (char v : value) paramsBuf[paramsLength++] = (byte)v;
    return this;
  }

  private static final int E_GENERAL = 0xff010001;
  private static final int E_BADARG = 0xff010002;
  private static final int E_TOO_SMALL = 0xff010008;

  private static int exceptionToRv(Exception e)
  {
    if (e==null) return 0;
    if (e instanceof IllegalArgumentException) return E_BADARG;
    if (e instanceof ShortBufferException) return E_TOO_SMALL;
    return E_GENERAL;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy