Java tutorial
package ar.com.allium.rules.core.service; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.web.context.WebApplicationContext; import ar.com.allium.rules.core.annotation.ExecuteRule; import ar.com.allium.rules.core.annotation.Rule; import ar.com.allium.rules.core.annotation.AlliumRuleSet; import ar.com.allium.rules.core.exception.AlliumRuleConfigurationException; import ar.com.allium.rules.core.model.AlliumRule; /** * Copyright 2014 Joel del Valle <joelmarcosdelvalle@gmail.com> * * This file is part of allium-rules, project of allium-projects. * * allium-rules is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * allium-rules is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * allium-rules. If not, see <http://www.gnu.org/licenses/>. * * * @author joel.delvalle * * service to load and build rules or set of rules * */ @SuppressWarnings("rawtypes") public final class LoadAlliumRules { private static Logger log = Logger.getLogger(LoadAlliumRules.class); private static final String EMPTY_STRING = ""; private static final String ALLIUM_CORE_RULE_PACKAGE = "/ar/com/allium/rules/core"; private AlliumCoreRuleManager alliumRuleCore; private String basePackage; private ApplicationContext springContext; private List<AlliumRule> alliumRuleList; private List<Class<?>> clazzWithMethodThatAlliumRulesImplement; public LoadAlliumRules(ApplicationContext springContext) { this.basePackage = EMPTY_STRING; this.springContext = springContext; this.alliumRuleList = new ArrayList<AlliumRule>(); this.clazzWithMethodThatAlliumRulesImplement = new ArrayList<Class<?>>(); } public LoadAlliumRules(String basePackage, WebApplicationContext springContext) { if (basePackage.endsWith(".")) { basePackage = basePackage.substring(0, basePackage.length() - 1); } if (basePackage.endsWith(".*")) { basePackage = basePackage.substring(0, basePackage.length() - 2); } this.basePackage = basePackage; this.springContext = springContext; this.alliumRuleList = new ArrayList<AlliumRule>(); this.clazzWithMethodThatAlliumRulesImplement = new ArrayList<Class<?>>(); } public void loadAlliumRules() { log.debug("Load and Build AlliumRule"); this.loadAlliumRule(); log.debug("Total found " + alliumRuleList.size() + " AlliumRule"); this.buildRulesMap(); log.debug("Validate AlliumRule used"); this.validateExcuteRuleAnnotationParameters(); } private void validateExcuteRuleAnnotationParameters() { log.debug("Found " + this.clazzWithMethodThatAlliumRulesImplement.size() + " class with AlliumRule implementation"); for (Class<?> clazz : this.clazzWithMethodThatAlliumRulesImplement) { for (Method method : clazz.getMethods()) { ExecuteRule executeRuleAnnotation = method.getAnnotation(ExecuteRule.class); if (executeRuleAnnotation != null) { if (executeRuleAnnotation.ruleClass().length == 0 && executeRuleAnnotation.ruleSetName().length == 0) { throw new AlliumRuleConfigurationException( "Found error in ExecuteRule configuration. The method '" + method.getName() + "' in class " + clazz.getCanonicalName() + " has not properly declared annotation @ExecuteRule. Remember to declare a 'ruleClass' or 'ruleSetName'"); } } } } } private void buildRulesMap() { for (AlliumRule alliumRule : alliumRuleList) { AlliumRuleSet alliumRuleSet = alliumRule.getClass().getAnnotation(AlliumRuleSet.class); if (alliumRuleSet != null) { for (String setName : alliumRuleSet.alliumRuleSetNames()) { if (setName != null && setName.trim() != EMPTY_STRING) { getAlliumCoreRuleManager().addRule(setName, alliumRule); } } } else { getAlliumCoreRuleManager().addRule(alliumRule); } } } @SuppressWarnings("unchecked") private void loadAlliumRule() { Class[] classes = this.getClassesInPackage(this.basePackage, Rule.class); for (Class c : classes) { AlliumRule newInstance; try { newInstance = (AlliumRule) springContext.getBean(c); } catch (NoSuchBeanDefinitionException noBean) { try { newInstance = (AlliumRule) c.newInstance(); } catch (Exception e) { throw new AlliumRuleConfigurationException("Error to create AlliumRule", e); } } log.debug(" " + newInstance.getClass().getCanonicalName()); alliumRuleList.add(newInstance); } } private Class[] getClassesInPackage(String basePackage, Class<?> classType) { File directory = this.getPackageDirectory(basePackage); if (!directory.exists()) { throw new AlliumRuleConfigurationException( "Could not get directory resource for package " + basePackage + "."); } return this.getClassesInPackage(basePackage, directory, classType); } private File getPackageDirectory(String basePackage) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { throw new AlliumRuleConfigurationException("Can't get class loader."); } URL resource = classLoader.getResource(basePackage.replace('.', '/')); if (resource == null) { throw new AlliumRuleConfigurationException("Package " + basePackage + " not found on classpath."); } return new File(resource.getFile()); } @SuppressWarnings("unchecked") private Class[] getClassesInPackage(String basePackage, File directory, Class classType) { List<String> className = new ArrayList<String>(); this.findAllClassInPackage(directory.getAbsolutePath(), directory, className); List<Class> classes = new ArrayList<Class>(); for (String filename : className) { if (filename.endsWith(".class")) { String classname = this.buildClassname(basePackage, filename); try { Class<?> clazz = Class.forName(classname); if (clazz.getSuperclass() != null && clazz.getSuperclass().getCanonicalName() .equals(AlliumRule.class.getCanonicalName())) { if (clazz.getSuperclass().getAnnotation(classType) != null) { classes.add(clazz); } } if (this.haveAnyMethodWithAlliumRuleImplementation(clazz)) { this.clazzWithMethodThatAlliumRulesImplement.add(clazz); } } catch (ClassNotFoundException e) { log.error("Error creating class " + classname); } } } return classes.toArray(new Class[classes.size()]); } private boolean haveAnyMethodWithAlliumRuleImplementation(Class<?> clazz) { for (Method method : clazz.getMethods()) { if (method.getAnnotation(ExecuteRule.class) != null) { return true; } } return false; } private void findAllClassInPackage(String baseDirectory, File file, List<String> all) { try { File[] children = file.listFiles(); if (children != null) { for (File child : children) { if (!child.isDirectory() && !this.invalidDirecory(baseDirectory, file.getCanonicalPath())) { all.add(child.getAbsolutePath().substring(baseDirectory.length())); } findAllClassInPackage(baseDirectory, child, all); } } } catch (IOException ioe) { throw new AlliumRuleConfigurationException("Error to find AlliumRule"); } } private String buildClassname(String pckgname, String filename) { String classPath = pckgname + filename.replace(".class", "").replace("/", "."); if (classPath.startsWith(".")) { classPath = classPath.substring(1); } return classPath; } private boolean invalidDirecory(String baseDirectory, String filePath) { filePath = filePath.substring(baseDirectory.length()); return filePath.startsWith(ALLIUM_CORE_RULE_PACKAGE); } private AlliumCoreRuleManager getAlliumCoreRuleManager() { if (alliumRuleCore == null) { alliumRuleCore = springContext.getBean("alliumCoreRuleManager", AlliumCoreRuleManager.class); } return alliumRuleCore; } }