1   package org.test;
2   
3   import com.google.common.base.Preconditions;
4   import org.slf4j.*;
5   
6   import java.util.*;
7   import java.io.*;
8   import java.util.logging.Level;
9   import org.slf4j.Logger;
10  import org.slf4j.LoggerFactory;
11  import org.slf4j.ext.XLogger;
12  import org.slf4j.ext.XLoggerFactory;
13  
14  import static com.google.common.base.Preconditions.checkState;
15  
16  class LazyArgEvaluationCheck {
17  
18    public static final Logger slf4j = LoggerFactory.getLogger(LazyArgEvaluationCheck.class);
19    public static final java.util.logging.Logger logger = java.util.logging.Logger.getGlobal();
20    public static final org.apache.logging.log4j.Logger log4j = org.apache.logging.log4j.LogManager.getLogger();
21  
22    public static void main(String[] args) {
23      String csvPath = "";
24      String message = "";
25  
26      logger.log(Level.SEVERE, message); // Compliant
27  
28      logger.log(Level.SEVERE, "Something went wrong: " + message);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
29  
30      logger.log(Level.SEVERE, () -> "Something went wrong: " + message); // since Java 8, we can use Supplier , which will be evaluated lazily
31  
32      checkState(System.currentTimeMillis() == new Date().getTime(), "Arg must be positive, but got " + System.currentTimeMillis());  // Noncompliant {{Invoke method(s) only conditionally. Use the built-in formatting to construct this argument.}}
33  
34      Preconditions.checkState(System.currentTimeMillis() > 0, formatMessage());  // Noncompliant {{Invoke method(s) only conditionally. }}
35  
36      checkState(System.currentTimeMillis() > 0, "message: %s", formatMessage());  // Noncompliant {{Invoke method(s) only conditionally. }}
37  
38      checkState(System.currentTimeMillis() > 0, "message: %s", LazyArgEvaluationCheck.formatMessage());  // Noncompliant {{Invoke method(s) only conditionally. }}
39    }
40  
41    public static void cachingOnDisk(File path) {
42      slf4j.info("Caching on disk @ {}", path.getAbsolutePath()); // Compliant - getters are OK
43      slf4j.info("Caching on disk @ {}", path.isAbsolutePath()); // Compliant - getters are OK
44    }
45  
46    public void exceptionalPaths() {
47      try {
48  
49      } catch (Exception e) {
50        slf4j.info("Caching on disk @ {}", path.getAbsolutePath()); // Compliant - because we don't care about small performance loss in exceptional paths
51        myField = new MyClass() {
52          @Overidde
53          void doSomethingAllTheTime() {
54            slf4j.info("logging all the time consuming resources for nothing " + computeValue() + generateStuff()); // Noncompliant
55          }
56        };
57      }
58    }
59  
60    public void multiArgs() {
61      checkState(System.currentTimeMillis() > 0, "message: %s %s", formatMessage(), "Something went wrong: " + System.currentTimeMillis());  // Noncompliant {{Invoke method(s) only conditionally. }}
62    }
63  
64    private static String formatMessage() {
65      return "Expensive computation";
66    }
67  
68    public void classTree() {
69      logger.log(Level.SEVERE, "Something went wrong: " + new Object() { // Noncompliant {{Invoke method(s) only conditionally. Use the built-in formatting to construct this argument.}}
70        @Override
71        public String toString() {
72          return "tostring";
73        }
74      });
75    }
76  
77    void slf4j(String csvPath) {
78      slf4j.trace("Unable to open file " + csvPath, new RuntimeException());  // Noncompliant {{Use the built-in formatting to construct this argument.}}
79      slf4j.debug("Unable to open file " + csvPath, new RuntimeException());  // Noncompliant {{Use the built-in formatting to construct this argument.}}
80      slf4j.info("Unable to open file " + csvPath, new RuntimeException());  // Noncompliant {{Use the built-in formatting to construct this argument.}}
81      slf4j.warn("Unable to open file " + csvPath, new RuntimeException());  // Noncompliant {{Use the built-in formatting to construct this argument.}}
82      slf4j.error("Unable to open file " + csvPath, new RuntimeException());  // Noncompliant {{Use the built-in formatting to construct this argument.}}
83  
84      slf4j.error("Unable to open file " + csvPath, new RuntimeException());  // Noncompliant
85      slf4j.error("Unable to open file " + csvPath, new RuntimeException(), 1);  // Noncompliant
86      slf4j.error("Unable to open file " + csvPath, new RuntimeException(), 1, 2);  // Noncompliant
87      slf4j.error("Unable to open file " + csvPath, new RuntimeException(), 1, "vargs", "vargs", "vargs FTW!");  // Noncompliant
88  
89      Marker confidentialMarker = MarkerFactory.getMarker("CONFIDENTIAL");
90      slf4j.error(confidentialMarker, "Unable to open file " + csvPath, new RuntimeException());  // Noncompliant
91      slf4j.error(confidentialMarker, "Unable to open file " + csvPath, new RuntimeException(), 1);  // Noncompliant
92      slf4j.error(confidentialMarker, "Unable to open file " + csvPath, new RuntimeException(), 1, 2);  // Noncompliant
93      slf4j.error(confidentialMarker, "Unable to open file " + csvPath, new RuntimeException(), 1, "vargs", "vargs", "vargs FTW!");  // Noncompliant
94  
95      if (slf4j.isTraceEnabled()) {
96        slf4j.trace("Unable to open file " + csvPath, new RuntimeException());  // Compliant - inside if test
97      }
98      if (slf4j.isDebugEnabled()) {
99        slf4j.debug("Unable to open file " + csvPath, new RuntimeException());  // Compliant - inside if test
100     }
101     if (slf4j.isInfoEnabled()) {
102       slf4j.info("Unable to open file " + csvPath, new RuntimeException());  // Compliant - inside if test
103     }
104     if (slf4j.isWarnEnabled()) {
105       slf4j.warn("Unable to open file " + csvPath, new RuntimeException());  // Compliant - inside if test
106     }
107     if (slf4j.isErrorEnabled()) {
108       slf4j.error("Unable to open file " + csvPath, new RuntimeException());  // Compliant - inside if test
109     }
110     if (b) {
111       slf4j.error("Unable to open file " + csvPath, new RuntimeException());  // Noncompliant
112     }
113   }
114 
115   void jul(String csvPath) {
116     logger.finest("Unable to open file " + csvPath);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
117     logger.finer("Unable to open file " + csvPath);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
118     logger.fine("Unable to open file " + csvPath);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
119     logger.config("Unable to open file " + csvPath);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
120     logger.info("Unable to open file " + csvPath);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
121     logger.warning("Unable to open file " + csvPath);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
122     logger.severe("Unable to open file " + csvPath);  // Noncompliant {{Use the built-in formatting to construct this argument.}}
123 
124     if (logger.isLoggable(Level.FINEST)) {
125       logger.finest("Unable to open file " + csvPath);  // Compliant - inside if test
126     }
127 
128     if (logger.isLoggable(Level.INFO)) {
129       logger.trace("Unable to open file " + csvPath);  // Compliant - FN, we don't verify that level in "if" matches actual level used in logging
130       logger.info("Unable to open file " + csvPath);  // Compliant
131     }
132   }
133 
134   void log4j(String csvPath, org.apache.logging.log4j.Marker marker) {
135     log4j.log(org.apache.logging.log4j.Level.DEBUG, "Unable to open file " + csvPath); // Noncompliant {{Use the built-in formatting to construct this argument.}}
136     log4j.debug("Unable to open file " + csvPath); // Noncompliant
137     log4j.error("Unable to open file " + csvPath); // Noncompliant
138     log4j.fatal("Unable to open file " + csvPath); // Noncompliant
139     log4j.info("Unable to open file " + csvPath); // Noncompliant
140     log4j.trace("Unable to open file " + csvPath); // Noncompliant
141     log4j.warn("Unable to open file " + csvPath); // Noncompliant
142 
143     if (log4j.isDebugEnabled()) {
144       log4j.debug("Unable to open file " + csvPath);
145     }
146     if (log4j.isEnabled(org.apache.logging.log4j.Level.DEBUG)) {
147       log4j.debug("Unable to open file " + csvPath);
148     }
149     if (log4j.isEnabled(org.apache.logging.log4j.Level.DEBUG, marker)) {
150       log4j.debug("Unable to open file " + csvPath);
151     }
152     log4j.debug(() -> "hello"); // using supplier
153     log4j.debug(() -> new org.apache.logging.log4j.message.StringFormatterMessageFactory().newMessage("Unable to open file " + csvPath));
154     log4j.debug("Unable to open file {0}", csvPath);
155   }
156 
157 }
158 
159 class A {
160   private static final Logger LOGGER = LoggerFactory.getLogger(A.class);
161   private static final XLogger X_LOGGER = XLoggerFactory.getXLogger(A.class);
162 
163   void foo(int timeout, String units) {
164     LOGGER.debug("Setting read timeout to " + timeout + " " + units); // Noncompliant
165     X_LOGGER.debug("Setting read timeout to " + timeout + " " + units); // Noncompliant
166   }
167 }
168 
169 class constantInlining {
170   Logger logger = LoggerFactory.getLogger(A.class);
171 
172   static final String MY_CONST = "world";
173   final String myField = "world";
174   static String myStaticField = "world";
175 
176   void foo(boolean answer) {
177     logger.warn("hello " + MY_CONST + ". Is this inlined by the compiler? {}", answer);
178     logger.warn("hello " + constantInlining.MY_CONST + ". Is this inlined by the compiler? {}", answer);
179     logger.warn("hello " + myField + ". Is this inlined by the compiler? {}", answer); // Noncompliant
180     logger.warn("hello " + myStaticField + ". Is this inlined by the compiler? {}", answer); // Noncompliant
181     logger.warn(MY_CONST + MY_CONST, answer);
182   }
183 }
184 
185 class AnnotationMethods {
186   Logger logger = LoggerFactory.getLogger(AnnotationMethods.class);
187   @interface MyAnnotation {
188     String someOtherValue();
189   }
190   void foo(MyAnnotation annotation){
191     logger.info("Caching on disk @ {}", annotation.someOtherValue()); // Compliant - annotation methods are OK
192   }
193 }