1 /*
   2  * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * A class to manage AccessBridge debugging
  28  */
  29 
  30 #include "AccessBridgeDebug.h"
  31 #include <stdarg.h>
  32 #include <stdio.h>
  33 #include <windows.h>
  34 #include <cstdlib>
  35 #include <chrono>
  36 #include <string>
  37 
  38 #ifdef __cplusplus
  39 extern "C" {
  40 #endif
  41 
  42 static FILE* logFP = nullptr;
  43 static std::string filePath;
  44 
  45 void initializeFileLogger(char * suffix) {
  46     const char* var = "JAVA_ACCESSBRIDGE_LOGFILE";
  47     const char* envfilePath = getenv(var);
  48     if (envfilePath != nullptr) {
  49         filePath = std::string(envfilePath);
  50         if (suffix != nullptr) {
  51             auto indx = filePath.find_last_of(".");
  52             filePath = indx != std::string::npos ?
  53                         filePath.substr(0, indx) + suffix + filePath.substr(indx) :
  54                         filePath + suffix + ".log";
  55         }
  56         logFP = fopen(filePath.c_str(), "w");
  57         if (logFP == nullptr) {
  58             PrintDebugString("couldnot open file %s", filePath);
  59         }
  60     }
  61 }
  62 
  63 void finalizeFileLogger() {
  64     if (logFP) {
  65         fclose(logFP);
  66         logFP = nullptr;
  67     }
  68 }
  69 
  70 auto getTimeStamp() -> long long {
  71     using namespace std::chrono;
  72     auto timeNow = duration_cast<milliseconds>(steady_clock::now().time_since_epoch());
  73 
  74     return timeNow.count();
  75 }
  76 
  77 /**
  78  * print a GetLastError message
  79  */
  80 char *printError(char *msg) {
  81     LPVOID lpMsgBuf = nullptr;
  82     static char retbuf[256] = {0};
  83 
  84     if (msg != nullptr) {
  85         strncpy((char *)retbuf, msg, sizeof(retbuf));
  86         // if msg text is >= 256 ensure buffer is null terminated
  87         retbuf[255] = '\0';
  88     }
  89     if (!FormatMessage(
  90                        FORMAT_MESSAGE_ALLOCATE_BUFFER |
  91                        FORMAT_MESSAGE_FROM_SYSTEM |
  92                        FORMAT_MESSAGE_IGNORE_INSERTS,
  93                        nullptr,
  94                        GetLastError(),
  95                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  96                        (LPTSTR) &lpMsgBuf,
  97                        0,
  98                        nullptr))
  99         {
 100             PrintDebugString("  %s: FormatMessage failed", msg);
 101         } else {
 102             PrintDebugString("  %s: %s", msg, (char *)lpMsgBuf);
 103         }
 104     if (lpMsgBuf != nullptr) {
 105         strncat((char *)retbuf, ": ", sizeof(retbuf) - strlen(retbuf) - 1);
 106         strncat((char *)retbuf, (char *)lpMsgBuf, sizeof(retbuf) - strlen(retbuf) - 1);
 107         LocalFree(lpMsgBuf);
 108     }
 109     return (char *)retbuf;
 110 }
 111 
 112 
 113     /**
 114      * Send debugging info to the appropriate place
 115      */
 116     void PrintDebugString(char *msg, ...) {
 117 #ifdef DEBUGGING_ON
 118         char buf[1024] = {0};
 119         va_list argprt;
 120 
 121         va_start(argprt, msg);     // set up argptr
 122         vsprintf(buf, msg, argprt);
 123 #ifdef SEND_TO_OUTPUT_DEBUG_STRING
 124         OutputDebugString(buf);
 125 #endif
 126 #ifdef SEND_TO_CONSOLE
 127         printf(buf);
 128         printf("\r\n");
 129 #endif
 130 #endif
 131         if (logFP) {
 132             fprintf(logFP, "[%lldu] ", getTimeStamp());
 133             va_list args;
 134             va_start(args, msg);
 135             vfprintf(logFP, msg, args);
 136             va_end(args);
 137             fprintf(logFP, "\r\n");
 138         }
 139     }
 140 
 141     /**
 142      * Send Java debugging info to the appropriate place
 143      */
 144     void PrintJavaDebugString2(char *msg, ...) {
 145 #ifdef JAVA_DEBUGGING_ON
 146         char buf[1024] = {0};
 147         va_list argprt;
 148 
 149         va_start(argprt, msg);     // set up argptr
 150         vsprintf(buf, msg, argprt);
 151 #ifdef SEND_TO_OUTPUT_DEBUG_STRING
 152         OutputDebugString(buf);
 153 #endif
 154 #ifdef SEND_TO_CONSOLE
 155         printf(buf);
 156         printf("\r\n");
 157 #endif
 158 #endif
 159         if (logFP) {
 160             fprintf(logFP, "[%llu] ", getTimeStamp());
 161             va_list args;
 162             va_start(args, msg);
 163             vfprintf(logFP, msg, args);
 164             va_end(args);
 165             fprintf(logFP, "\r\n");
 166         }
 167     }
 168     /**
 169      * Wide version of the method to send debugging info to the appropriate place
 170      */
 171     void wPrintDebugString(wchar_t *msg, ...) {
 172 #ifdef DEBUGGING_ON
 173         char buf[1024] = {0};
 174         char charmsg[256];
 175         va_list argprt;
 176 
 177         va_start(argprt, msg);          // set up argptr
 178         sprintf(charmsg, "%ls", msg);  // convert format string to multi-byte
 179         vsprintf(buf, charmsg, argprt);
 180 #ifdef SEND_TO_OUTPUT_DEBUG_STRING
 181         OutputDebugString(buf);
 182 #endif
 183 #ifdef SEND_TO_CONSOLE
 184         printf(buf);
 185         printf("\r\n");
 186 #endif
 187 #endif
 188         if (logFP) {
 189             fprintf(logFP, "[%llu] ", getTimeStamp());
 190             va_list args;
 191             va_start(args, msg);
 192             vfwprintf(logFP, msg, args);
 193             va_end(args);
 194             fprintf(logFP, "\r\n");
 195         }
 196     }
 197 
 198     /**
 199      * Wide version of the method to send Java debugging info to the appropriate place
 200      */
 201     void wPrintJavaDebugString(wchar_t *msg, ...) {
 202 #ifdef JAVA_DEBUGGING_ON
 203         char buf[1024] = {0};
 204         char charmsg[256] = {0};
 205         va_list argprt;
 206 
 207         va_start(argprt, msg);          // set up argptr
 208         sprintf(charmsg, "%ls", msg);  // convert format string to multi-byte
 209         vsprintf(buf, charmsg, argprt);
 210 #ifdef SEND_TO_OUTPUT_DEBUG_STRING
 211         OutputDebugString(buf);
 212 #endif
 213 #ifdef SEND_TO_CONSOLE
 214         printf(buf);
 215         printf("\r\n");
 216 #endif
 217 #endif
 218         if (logFP) {
 219             fprintf(logFP, "[%llu] ", getTimeStamp());
 220             va_list args;
 221             va_start(args, msg);
 222             vfwprintf(logFP, msg, args);
 223             va_end(args);
 224             fprintf(logFP, "\r\n");
 225         }
 226     }
 227 #ifdef __cplusplus
 228 }
 229 #endif