
org.swat.spring.SingletonVerifier Maven / Gradle / Ivy
/*
* Copyright © 2018 Swatantra Agrawal. All rights reserved.
*/
package org.swat.spring;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* The type Singleton verifier.
*/
public class SingletonVerifier {
private final String basePackage;
private Class[] springAnnotations =
new Class[]{Component.class, Controller.class, Repository.class, Service.class};
/**
* Instantiates a new Singleton verifier.
*
* @param baseBackage the base backage
*/
public SingletonVerifier(String baseBackage) {
this.basePackage = baseBackage;
}
/**
* Fail on instance fields.
*/
public void failOnInstanceFields() {
final Set instanceFields = getInstanceFields();
if (!instanceFields.isEmpty()) {
System.out.println("=============================");
System.out.println("Instance level fields are defined in a Singleton Object");
int counter = 0;
for (Field field : instanceFields) {
System.out.println(++counter + "\t" + field);
}
System.out.println("=============================");
System.out.println("Instance variables found in Singleton Objects. Check above logs.");
}
assert instanceFields.isEmpty();
}
/**
* Gets instance fields.
*
* @return the instance fields
*/
public Set getInstanceFields() {
final Set instanceFields = new HashSet<>();
Set> services = new HashSet<>();
for (Class clazz : springAnnotations) {
services.addAll(new Reflections(basePackage).getTypesAnnotatedWith(clazz));
}
for (Class> service : services) {
instanceFields.addAll(getInstanceFields(service));
}
return instanceFields;
}
/**
* Is test class boolean.
*
* @param service the service
* @return the boolean
*/
public static boolean isTestClass(Class> service) {
File file = new File(".");
String fileName = service.getName();
return isTestClass(file, fileName, 2);
}
/**
* Is test class boolean.
*
* @param folder the folder
* @param fileName the file name
* @param depth the depth
* @return the boolean
*/
public static boolean isTestClass(File folder, String fileName, int depth) {
if (depth < 0) {
return false;
}
if (!folder.isDirectory()) {
return false;
}
if (new File(folder, fileName).exists()) {
return true;
}
File[] files = folder.listFiles();
if (files == null) {
return false;
}
for (File file : files) {
if (isTestClass(file, fileName, depth - 1)) {
return true;
}
}
return false;
}
/**
* Populate fields.
*
* @param clazz the clazz
* @param fields the fields
*/
public static void populateFields(Class> clazz, Set fields) {
if (clazz == null || clazz == Object.class) {
return;
}
Field[] declaredFields = clazz.getDeclaredFields();
if (declaredFields != null) {
Collections.addAll(fields, declaredFields);
}
populateFields(clazz.getSuperclass(), fields);
}
/**
* Is service interface boolean.
*
* @param basePackage the base package
* @param type the type
* @return the boolean
*/
public static boolean isServiceInterface(String basePackage, Class> type) {
if (isTestClass(type)) {
return true;
}
Set extends Class>> subTypes = new Reflections(basePackage).getSubTypesOf(type);
if (subTypes == null) {
return false;
}
Iterator extends Class>> iterator = subTypes.iterator();
while (iterator.hasNext()) {
if (isTestClass(iterator.next())) {
iterator.remove();
}
}
return subTypes.size() == 1;
}
/**
* Gets instance fields.
*
* @param service the service
* @return the instance fields
*/
public Set getInstanceFields(Class> service) {
final Set instanceFields = new HashSet<>();
if (isTestClass(service)) {
return instanceFields;
}
Set allFields = new HashSet<>();
populateFields(service, allFields);
for (Field field : allFields) {
if (Modifier.isFinal(field.getModifiers())) {
continue;
}
if (field.isAnnotationPresent(IgnoredInstance.class)) {
continue;
}
if (field.isAnnotationPresent(Autowired.class)) {
continue;
}
if (field.isAnnotationPresent(Value.class)) {
continue;
}
if (isServiceInterface(basePackage, field.getType())) {
continue;
}
if (!isInstance(field)) {
continue;
}
instanceFields.add(field);
}
return instanceFields;
}
/**
* Hook to add more validations.
*
* @param field the field
* @return the boolean
*/
protected boolean isInstance(Field field) {
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy