1+ /*
2+ * Copyright 2024 Code Intelligence GmbH
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ *
16+ * This file was adapted from Jazzer (https://github.com/CodeIntelligenceTesting/jazzer)
17+ * to keep the agent lean by avoiding external logging dependencies.
18+ */
19+
20+ package com .github .serj .jcapslock .agent ;
21+
22+ import java .io .PrintStream ;
23+
24+ /**
25+ * Provides static functions that should be used for any kind of output emitted by the agent.
26+ *
27+ * <p>Output is printed to {@link System#err} and {@link System#out} until {@link
28+ * Log#fixOutErr(PrintStream, PrintStream)} is called, which locks in the {@link PrintStream}s to be
29+ * used from there on.
30+ */
31+ public class Log {
32+
33+ private static final String PREFIX = "[CAPSLOCK] " ;
34+
35+ // Don't use directly, always use getOut() and getErr() instead - when these fields haven't been
36+ // set yet, we want to resolve them dynamically as System.out and System.err, which may change
37+ // over the course of the agent's lifetime.
38+ private static PrintStream fixedOut ;
39+ private static PrintStream fixedErr ;
40+
41+ // Whether to print debug messages. This is controlled by the CAPSLOCK_DEBUG environment variable.
42+ private static final boolean isDebug = System .getenv ("CAPSLOCK_DEBUG" ) != null ;
43+
44+ /** The {@link PrintStream}s to use for all output from this call on. */
45+ public static void fixOutErr (PrintStream out , PrintStream err ) {
46+ if (out == null ) {
47+ throw new IllegalArgumentException ("out must not be null" );
48+ }
49+ if (err == null ) {
50+ throw new IllegalArgumentException ("err must not be null" );
51+ }
52+ Log .fixedOut = out ;
53+ Log .fixedErr = err ;
54+ }
55+
56+ public static void println (String message ) {
57+ getErr ().println (message );
58+ }
59+
60+ public static void structuredOutput (String output ) {
61+ getOut ().println (output );
62+ }
63+
64+ public static void debug (String message ) {
65+ if (isDebug ) {
66+ println (PREFIX , "DEBUG: " + message , null );
67+ }
68+ }
69+
70+ public static void info (String message ) {
71+ println (PREFIX , message , null );
72+ }
73+
74+ public static void warn (String message ) {
75+ warn (message , null );
76+ }
77+
78+ public static void warn (String message , Throwable t ) {
79+ println (PREFIX , "WARN: " + message , t );
80+ }
81+
82+ public static void error (String message ) {
83+ error (message , null );
84+ }
85+
86+ public static void error (Throwable t ) {
87+ error (null , t );
88+ }
89+
90+ public static void error (String message , Throwable t ) {
91+ println (PREFIX , "ERROR: " + message , t );
92+ }
93+
94+ private static void println (String prefix , String message , Throwable t ) {
95+ PrintStream err = getErr ();
96+ err .print (prefix );
97+ if (message != null ) {
98+ err .println (message + (t != null ? ":" : "" ));
99+ }
100+ if (t != null ) {
101+ t .printStackTrace (err );
102+ }
103+ }
104+
105+ private static PrintStream getOut () {
106+ return fixedOut != null ? fixedOut : System .out ;
107+ }
108+
109+ private static PrintStream getErr () {
110+ return fixedErr != null ? fixedErr : System .err ;
111+ }
112+ }
0 commit comments