How find specific code occurrences in java code with sonar rule - java

I wish to give developers suggestion that for example: System.currentTimeMillis() is not recommended and provide some comments with alternative solutions.
AFAIK there is no such sonar rule, should I create a new one or there is an option to parametrize existing one?
I found that xpath for java is no longer supported, so am I right that writing custom rule is the only way?

You're looking for template rule S2253, which allows you to flag calls to a specific method.

Here's example of setting custom method warnings using sonar:
#Rule(key = "NoObjectWaitRule",
name = "NoObjectWaitRule",
description = "You should not use classic wait/notify mechanism. Instead use Java Concurrency API.",
priority = Priority.MAJOR,
tags =
{
"bad-practice"
})
public class NoObjectWaitRule extends DisallowedMethodCheck
{
public NoObjectWaitRule()
{
super.setClassName("java.lang.Object");
super.setMethodName("wait");
super.setAllOverloads(true);
}
}

Related

Use of fluent interfaces to validate objects using java 8

Im currently doing a side project to validate objects using java 8.
Currently I have this:
An interface that is essencially a rewrite of the java 8 predicate interface:
Then, I created the implementation of that same interface:
And then this class is the result of my validation
The concrete object validation can be found here:
public class ConcreteValidator implements EmployeeValidator {
#Override
public void validate(Employee employee) throws EmployeeException {
ValidatorUtil.notNullString.and(ValidatorUtil.notEmptyString)
.and(ValidatorUtil.stringBetween(1, 100)).test(employee.getFirstName())
.getFieldNameIfInvalid(" Please specify valid firstname ").orElse("");
ValidatorUtil.notNullString.and(ValidatorUtil.notEmptyString)
.and(ValidatorUtil.stringBetween(1, 100)).test(employee.getLastName())
.getFieldNameIfInvalid(" Please specify valid lastname ").orElse("");
ValidatorUtil.notNullString.and(ValidatorUtil.notEmptyString)
.and(ValidatorUtil.stringBetween(3, 100)).test(employee.getEmail())
.getFieldNameIfInvalid(" Please specify valid email ").orElse("");
ValidatorUtil.notNullInteger.and(ValidatorUtil.greaterThanZero)
.and(ValidatorUtil.integerBetween(18, 60)).test(employee.getAge())
.getFieldNameIfInvalid(" Please specify valid age ").orElse("");
}
}
This works fine but what I want to do now is to limit the user to use the notNull verification first, and only after that validation all the methods like notEmpty or greaterThanZero will be available.
I searched for fluent interfaces but don't know if it is the correct way to do it (want to do something like this: https://code-held.com/2019/04/29/robust-builder-pattern/)
To summarise, I want to force the developer to validate if the object is null first and all the other methods go next, something like the chaining of the Stream API in java-8.Here is my customValidations.
You can't, not with how you do your methods: <K> GenericValidation<K> from(Predicate<K> predicate).
By doing so, you tell the developer he can pass any Java expressions: you can't validate the content of the expression at runtime, unlike you want to play with bytecode - which you don't.
You need to enforce this using the compiler, for example:
GenericValidation<K> fromNonNull(Predicate<K> predicate) {
return from(val -> val != null && predicate.test(val));
}
Or using types as shown below:
validateThat(employee.getFirstName()) // return a StringValidator1
.isNotNull() // return a StringValidator2
.isNotEmpty()
.hasLengthBetween(1, 100)
;
StringValidator1 only have isNotNull() and return StringValidator2.
That's how you would enforce the isNotNull() check with the compiler: by returning another type providing more services than the default. Since StringValidator1 does not have isNotEmpty(), then the compiler would generate a compilation error by trying to call it.
You may read AssertJ code for how they do their fluent interface. There are of course other source code being fluent (and I think the most important part of "fluent", is that the compiler and IDE helps you in validating what you are doing).

Drools DSL custom expander

There is dsl.DefaultExpander and dsl.DefaultExpanderResolver. Design and javadoc gives an idea I can add my custom expander to the flow. But I didn't found real possibility to do that. Do you see how could I achieve DSL to parsed with my custom expander?
Well, in KnowledgeBuilderImpl (the class used to compile DRL/DSL) I see the following method:
public DefaultExpander getDslExpander() {
DefaultExpander expander = new DefaultExpander();
if (this.dslFiles == null || this.dslFiles.isEmpty()) {
return null;
}
for (DSLMappingFile file : this.dslFiles) {
expander.addDSLMapping(file.getMapping());
}
return expander;
}
As you can see, DefaultExpander is hardcoded in there, so I guess there is no way to specify any other implementation.
Same thing happens in DrlParser.getDefaultResolver() where a DefaultExpanderResolver is always instantiated no matters what.
In my opinion, the only way to go is to pre-generate your DRL (outside Drools) based on your own semantics and then to feed the generated DRL to Drools.
Hope it helps,

ui binder pattern: initializing variables using generators

I am trying to create a GWT generator that does the following:
public class MyPool {
#InitializeThisVariable
Element1 el1;
#InitializeThisVariable
Element2 el2;
private static final ChildPool childPool = GWT
.create(ChildPool.class);
interface ChildPool extends Pool<MyPool>{}
public MyPool(){
}
}
I want the generator to initialize the annotated fields. After doing some research, I have found out that the only way to do this is to use the pattern used by ui-binder as above (I do not want to use Annotations Processors).
However I get the following error when compiling:
[ERROR] Line 16: Rebind result 'ChildPool' must be a class
Help would be much appreciated.
Your generator needs to return name if the generated class. Either that or you forgot the <generate-with> in your module.
Also, your code doesn't make use of the generated Pool instance.
Note however that generators are being deprecated in GWT 2.8, and you should really use other kind of code generators (be it annotation processors or something else). You shouldn't start writing new generators nowadays.

How to use the log4j2 wrapper API

I do have some trouble understanding the log4j2 wrapper usage.
If you follow this link you will find attached an example using the AbstractLoggerWrapper. I just copied the following peace of code.
public class Log4j2Logger extends AbstractLogger
{
private static final String FQCN = AbstractLogger.class.getName();
private AbstractLoggerWrapper logImpl;
public Log4j2Logger(String name, String prefix, String logId, String instanceId)
{
super(name, prefix, logId, instanceId);
final AbstractLogger logger = (AbstractLogger) LogManager.getLogger(name);
this.logImpl = new AbstractLoggerWrapper(logger, name);
}
....
#Override
public void log(String message, LogLevel level)
{
logImpl.log(null, FQCN, toImplLevel(level), new SimpleMessage(createMessage(message)), null);
}
....
}
I don't understand the reason for subclassing AbstractLogger and intern using the AbstractLoggerWrapper. I actually could just remove the extend from the Log4j2Logger and encapsulate the AbstractLoggerWrapper. Do you see any reason of doing it like in the code snipped above?
Is there any way to subclass the AbstractLogger (like preferred) and just use it without the wrapper? And create it like a strategy pattern? e.g.,
LogManager.getLogger( class.getName(), Log4j2Logger.class )
Maybe this is what they tried to explain in the extending section and I don't understand it, yet. Somebody any idea how to do it?
Sincerely
Christian
Update: I missed to say, the reason why I am using the wrapper is because of an existing projekt with log4j (1.2) with a wrapper.
If you look at the documentation for AbstractLoggerWrapper:
Wrapper class that exposes the protected AbstractLogger methods to
support wrapped loggers.
You will see a clear indication as to why it is done the way Apache does it. If you instead decide to ignore the contract of the interface and go your own way, you are essentially saying
"I don't care how the library does things, I know better"
As such, you are taking on a great deal of risk, instead of using the general solution that has been provided. I sincerely doubt that you have such an esoteric environment that the library could would be insufficient.
To recap, follow the contract laid out by the library documentation.

Modify a method using Annotations

How can I change what a method is doing in Java ?
I mean, I am trying to use annotations to make the following code
#Anno1(Argument = "Option1")
public class TestClass
{
#Anno2
public void test()
{
}
}
Into
public class TestClass
{
private static StaticReference z;
public void test()
{
z.invokeToAll();
}
}
This is a very simplified example of what I am trying to do. Anno1 will have many possible combinations, but this is not my problem so far. My problem is how to add code to method test()
I am looking for a more generic solution if possible. Eg. A way to add every kind of code in the method (not just a way to .invokeToAll())
So far I am using import javax.annotation.processing.*; and I have the following code, but I don't know how to go on from there
private void processMethodAnnotations(RoundEnvironment env)
{
for (Element e : env.getElementsAnnotatedWith(Anno2.class))
{
//If it is a valid annotation over a method
if (e.getKind() == ElementKind.METHOD)
{
//What to do here :S
}else
{
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,"Not a method!", e);
}
}
}
I have found something about Java Reflection but I have not found any source to help me with what I am doing.
Obviously I extends AbstractProcessor in my code
I have found this tutorial (http://www.zdnetasia.com/writing-and-processing-custom-annotations-part-3-39362483.htm) But this concerns creating a new class, not just changing a method. and the javax.lang.model.elements do not provide any way of editing that element (which in my case represents a Method).
I hope my question is clear and inline with the rules. If not please comment and I will clarify. Thanks.
Annotation processing is the wrong way to go for you, from Wikipedia:
When Java source code is compiled,
annotations can be processed by
compiler plug-ins called annotation
processors. Processors can produce
informational messages or create
additional Java source files or
resources, which in turn may be
compiled and processed, but annotation
processors cannot modify the annotated
code itself.
People suggested to you the right way - AOP. Specifically, you can use AspectJ. "Quick result" way is (if you use Eclipse):
Install AJDT (AspectJ Development Tools)
Create an AspectJ project and add there your classes and annotations
Create Aspect:
public aspect Processor {
private StaticReference z;
pointcut generic()
// intercept execution of method named test, annotated with #Anno1
// from any class type, annotated with #Anno2
: execution(#Anno2 * (#Anno1 *).test())
// method takes no arguments
&& args ();
// here you have written what you want the method to actually do
void around () : generic() {
z.invokeToAll();
}
}
now you can execute a test and you will see that it works ;) AJDT compiles code for you automatically, so do not need any manual work to do, hope that's what you called "magic" ;)
UPDATE:
if your code in the test() method depends on the Anno1 annotation value, then inside aspect you can get class annotation for which it is executed this way:
void around () : generic() {
Annotation[] classAnnotations = thisJoinPoint.getThis().getClass().getAnnotations();
String ArgumentValue = null;
for ( Annotation annotation : classAnnotations ) {
if ( annotation instanceof Anno1 ) {
ArgumentValue = ((Anno1) annotation).Argument();
break;
}
}
if ( ArgumentValue != null && ArgumentValue.equals("Option1")) {
z.invokeToAll();
}
}
where thisJoinPoint is a special reference variable.
UPDATE2:
if you want to add System.out.println( this ) in your aspect, you need to write there System.out.println( thisJoinPoint.getThis() ), just tested and it works. thisJoinPoint.getThis() returns you "this" but not exactly; in fact this is Object variable and if you want to get any propery you need either to cast or to use reflection. And thisJoinPoint.getThis() does not provide access to private properties.
Well, now seems that your question is answered, but if I missed anything, or you get additional question/problems with this way - feel free to ask ;)
It's perfectly possible to do what you ask, although there is a caveat: relying on private compiler APIs. Sounds scary, but it isn't really (compiler implementations tend to be stable).
There's a paper that explains the procedure: The Hacker's Guide to Javac.
Notably, this is used by Project Lombok to provide automatic getter/setter generation (amongst other things). The following article explains how it does it, basically re-iterating what is said the aforementioned paper.
Well, you might see if the following boilerplate code will be useful:
public void magic(Object bean, String[] args) throws Exception {
for (Method method : bean.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(Anno2.class)) {
// Invoke the original method
method.invoke(bean, args);
// Invoke your 'z' method
StaticReference.invokeAll();
}
}
}
As an alternative your might employ aspect oriented programming, for instance you have the AspectJ project.
I'm not sure at all if it is even possible to change the source or byte code via annotations. From what your describing it looks as if aspect oriented programming could provide a solution to your problem.
Your annotations are pretty similiar to the pointcut concept (they mark a location where code needs to be inserted) and the inserted code is close the advice concept.
Another approach would be parsing the java source file into an abstract syntax tree, modify this AST and serialize to a java compiler input.
If your class extends a suitable interface, you could wrap it in a DynamicProxy, which delegates all calls to the original methods, except the call to test.

Categories