2121
2222package com .wolfssl .provider .jce ;
2323
24+ import java .sql .Timestamp ;
25+ import java .util .logging .*;
26+ import java .util .logging .Formatter ;
27+ import java .util .logging .Handler ;
28+ import java .util .function .Supplier ;
29+
2430class WolfCryptDebug {
2531
32+ private static final Logger jceLogger =
33+ Logger .getLogger ("com.wolfssl.provider.jce" );
34+
2635 public static boolean DEBUG = checkProperty ();
2736
37+ /** Error level debug message */
38+ public static final String ERROR = "ERROR" ;
39+
40+ /** Info level debug message */
41+ public static final String INFO = "INFO" ;
42+
43+ static {
44+ configureLoggers ();
45+ }
46+
47+ /**
48+ * Custom handler that flushes after each log record
49+ */
50+ private static class FlushingStreamHandler extends StreamHandler {
51+ public FlushingStreamHandler () {
52+ super (System .err , new WolfCryptFormatter ());
53+ }
54+
55+ @ Override
56+ public synchronized void publish (LogRecord record ) {
57+ super .publish (record );
58+ flush ();
59+ }
60+ }
61+
62+ /**
63+ * Configure loggers based on system properties
64+ */
65+ private static void configureLoggers () {
66+ /* Remove any existing handlers */
67+ for (Handler handler : jceLogger .getHandlers ()) {
68+ jceLogger .removeHandler (handler );
69+ }
70+
71+ /* Only configure handlers if debug is enabled */
72+ if (DEBUG ) {
73+ /* Create custom handler that flushes after each log record */
74+ FlushingStreamHandler handler = new FlushingStreamHandler ();
75+ handler .setFormatter (new WolfCryptFormatter ());
76+ jceLogger .addHandler (handler );
77+ }
78+
79+ /* Set log levels based on debug properties */
80+ jceLogger .setLevel (DEBUG ? Level .ALL : Level .OFF );
81+
82+ /* Disable parent handlers to prevent double logging */
83+ jceLogger .setUseParentHandlers (false );
84+ }
85+
86+ /**
87+ * Custom formatter for log records
88+ */
89+ private static class WolfCryptFormatter extends Formatter {
90+ @ Override
91+ public String format (LogRecord record ) {
92+ if (record == null ) {
93+ return "null record\n " ;
94+ }
95+
96+ String sourceClass = record .getSourceClassName ();
97+ if (sourceClass == null ) {
98+ sourceClass = "" ;
99+ } else {
100+ /* Extract simple class name (after last dot) */
101+ int lastDot = sourceClass .lastIndexOf ('.' );
102+ if (lastDot != -1 ) {
103+ sourceClass = sourceClass .substring (lastDot + 1 );
104+ }
105+ }
106+
107+ Level level = record .getLevel ();
108+ String levelStr = level != null ? level .getName () : "UNKNOWN" ;
109+
110+ long threadId = record .getThreadID ();
111+ String message = record .getMessage ();
112+ if (message == null ) {
113+ message = "" ;
114+ }
115+
116+ return String .format ("%s [%s %s: TID %d: %s] %s\n " ,
117+ new Timestamp (record .getMillis ()),
118+ "wolfJCE" ,
119+ levelStr ,
120+ threadId ,
121+ sourceClass ,
122+ message );
123+ }
124+ }
125+
28126 private static boolean checkProperty () {
29127
30128 String enabled = System .getProperty ("wolfjce.debug" );
@@ -36,10 +134,61 @@ private static boolean checkProperty() {
36134 return false ;
37135 }
38136
39- public static void print (String string ) {
40- if (DEBUG ) {
41- System .out .println ("wolfJCE: " + string );
137+ /**
138+ * Refresh debug enabled/disabled flags based on current
139+ * System properties.
140+ */
141+ public static synchronized void refreshDebugFlags () {
142+ boolean oldDebug = DEBUG ;
143+
144+ DEBUG = checkProperty ();
145+
146+ /* Only reconfigure if debug state has changed */
147+ if (oldDebug != DEBUG ) {
148+ configureLoggers ();
42149 }
43150 }
44- }
45151
152+ /**
153+ * Print out debug message if debugging is enabled.
154+ *
155+ * @param <T> class type of cl
156+ * @param cl class being called from to get debug info
157+ * @param tag level of debug message, ie WolfCryptDebug.INFO
158+ * @param messageSupplier supplier of message to be printed out
159+ */
160+ public static synchronized <T > void log (Class <T > cl , String tag ,
161+ Supplier <String > messageSupplier ) {
162+
163+ log (cl , "wolfJCE" , tag , 0 , messageSupplier );
164+ }
165+
166+ /**
167+ * Print out debug message if debugging is enabled.
168+ *
169+ * @param <T> class type of cl
170+ * @param cl class being called from to get debug info
171+ * @param component component name, ie "wolfJCE"
172+ * @param tag level of debug message, ie WolfCryptDebug.INFO
173+ * @param nativePtr native pointer
174+ * @param messageSupplier supplier of message to be printed out
175+ */
176+ public static synchronized <T > void log (Class <T > cl , String component ,
177+ String tag , long nativePtr , Supplier <String > messageSupplier ) {
178+
179+ if (!DEBUG ) {
180+ return ;
181+ }
182+
183+ Level level = tag .equals (ERROR ) ? Level .SEVERE : Level .INFO ;
184+
185+ String className = cl .getSimpleName ();
186+ if (nativePtr != 0 ) {
187+ className = className + ": " + nativePtr ;
188+ }
189+
190+ LogRecord record = new LogRecord (level , messageSupplier .get ());
191+ record .setSourceClassName (cl .getName ());
192+ jceLogger .log (record );
193+ }
194+ }
0 commit comments