001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2017 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.utils; 021 022import java.io.IOException; 023import java.lang.reflect.Modifier; 024import java.util.Collection; 025import java.util.Set; 026import java.util.stream.Collectors; 027 028import com.google.common.reflect.ClassPath; 029import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 030import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; 031import com.puppycrawl.tools.checkstyle.api.AutomaticBean; 032import com.puppycrawl.tools.checkstyle.api.BeforeExecutionFileFilter; 033import com.puppycrawl.tools.checkstyle.api.Filter; 034import com.puppycrawl.tools.checkstyle.api.RootModule; 035 036/** 037 * Contains utility methods for module reflection. 038 * @author LuoLiangchen 039 */ 040public final class ModuleReflectionUtils { 041 042 /** Prevent instantiation. */ 043 private ModuleReflectionUtils() { 044 } 045 046 /** 047 * Gets checkstyle's modules (directly, not recursively) in the given packages. 048 * @param packages the collection of package names to use 049 * @param loader the class loader used to load Checkstyle package names 050 * @return the set of checkstyle's module classes 051 * @throws IOException if the attempt to read class path resources failed 052 * @see #isCheckstyleModule(Class) 053 */ 054 public static Set<Class<?>> getCheckstyleModules( 055 Collection<String> packages, ClassLoader loader) throws IOException { 056 final ClassPath classPath = ClassPath.from(loader); 057 return packages.stream() 058 .flatMap(pkg -> classPath.getTopLevelClasses(pkg).stream()) 059 .map(ClassPath.ClassInfo::load) 060 .filter(ModuleReflectionUtils::isCheckstyleModule) 061 .collect(Collectors.toSet()); 062 } 063 064 /** 065 * Checks whether a class may be considered as a checkstyle module. Checkstyle's modules are 066 * non-abstract classes, which are either checkstyle's checks, file sets, filters, file filters, 067 * or root module. 068 * @param clazz class to check. 069 * @return true if the class may be considered as the checkstyle module. 070 */ 071 public static boolean isCheckstyleModule(Class<?> clazz) { 072 return isValidCheckstyleClass(clazz) 073 && (isCheckstyleCheck(clazz) 074 || isFileSetModule(clazz) 075 || isFilterModule(clazz) 076 || isFileFilterModule(clazz) 077 || isRootModule(clazz)); 078 } 079 080 /** 081 * Checks whether a class extends 'AutomaticBean' and is non-abstract. 082 * @param clazz class to check. 083 * @return true if a class may be considered a valid production class. 084 */ 085 public static boolean isValidCheckstyleClass(Class<?> clazz) { 086 return AutomaticBean.class.isAssignableFrom(clazz) 087 && !Modifier.isAbstract(clazz.getModifiers()); 088 } 089 090 /** 091 * Checks whether a class may be considered as the checkstyle check. 092 * Checkstyle's checks are classes which implement 'AbstractCheck' interface. 093 * @param clazz class to check. 094 * @return true if a class may be considered as the checkstyle check. 095 */ 096 public static boolean isCheckstyleCheck(Class<?> clazz) { 097 return AbstractCheck.class.isAssignableFrom(clazz); 098 } 099 100 /** 101 * Checks whether a class may be considered as the checkstyle file set. 102 * Checkstyle's file sets are classes which implement 'AbstractFileSetCheck' interface. 103 * @param clazz class to check. 104 * @return true if a class may be considered as the checkstyle file set. 105 */ 106 public static boolean isFileSetModule(Class<?> clazz) { 107 return AbstractFileSetCheck.class.isAssignableFrom(clazz); 108 } 109 110 /** 111 * Checks whether a class may be considered as the checkstyle filter. 112 * Checkstyle's filters are classes which implement 'Filter' interface. 113 * @param clazz class to check. 114 * @return true if a class may be considered as the checkstyle filter. 115 */ 116 public static boolean isFilterModule(Class<?> clazz) { 117 return Filter.class.isAssignableFrom(clazz); 118 } 119 120 /** 121 * Checks whether a class may be considered as the checkstyle file filter. 122 * Checkstyle's file filters are classes which implement 'BeforeExecutionFileFilter' interface. 123 * @param clazz class to check. 124 * @return true if a class may be considered as the checkstyle file filter. 125 */ 126 public static boolean isFileFilterModule(Class<?> clazz) { 127 return BeforeExecutionFileFilter.class.isAssignableFrom(clazz); 128 } 129 130 /** 131 * Checks whether a class may be considered as the checkstyle root module. 132 * Checkstyle's root modules are classes which implement 'RootModule' interface. 133 * @param clazz class to check. 134 * @return true if a class may be considered as the checkstyle root module. 135 */ 136 public static boolean isRootModule(Class<?> clazz) { 137 return RootModule.class.isAssignableFrom(clazz); 138 } 139}