Java tutorial
/* * Copyright 2012 Grid Dynamics Consulting Services, Inc. * http://www.griddynamics.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.griddynamics.banshun; import com.griddynamics.banshun.config.xml.ParserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionValidationException; import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry; import org.springframework.beans.factory.xml.ResourceEntityResolver; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import java.text.MessageFormat; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * @author Alexey Olenev */ public class StrictContextParentBean extends ContextParentBean implements BeanNameAware { private static final Logger log = LoggerFactory.getLogger(StrictContextParentBean.class); private String name; private List<String> runOnlyServices = new ArrayList<>(); private LocationsGraph locationsGraph; private boolean prohibitCycles = true; public void setProhibitCycles(boolean prohibitCycles) { this.prohibitCycles = prohibitCycles; } public String getName() { return name; } public void setBeanName(String name) { this.name = name; } public void setRunOnlyServices(String[] runOnlyServices) { List<String> runOnly = new ArrayList<>(); for (String service : runOnlyServices) { runOnly.add(service + EXPORT_REF_SUFFIX); } this.runOnlyServices = runOnly; } @Override protected void addToFailedLocations(String loc) { locationsGraph.transitiveClosure(loc, ignoredLocations, false); } @Override protected List<String> analyzeDependencies(List<String> configLocations) throws Exception { ContextAnalyzer analyzer = new ContextAnalyzer(); List<Exception> exceptions = new LinkedList<>(); List<String> limitedLocations = new ArrayList<>(); for (String loc : configLocations) { BeanDefinitionRegistry beanFactory = getBeanFactory(loc); String[] beanNames = beanFactory.getBeanDefinitionNames(); for (String beanName : beanNames) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); try { if (isExport(beanDefinition)) { analyzer.addExport(beanDefinition); if (checkForRunOnly(beanName)) { limitedLocations.add(loc); } } else if (isImport(beanDefinition)) { analyzer.addImport(beanDefinition); } else if (beanDefinition.getBeanClassName() != null) { checkClassExist(loc, beanName, beanDefinition.getBeanClassName()); } } catch (Exception ex) { exceptions.add(ex); } } } analyzer.areThereExportsWithoutImport(); if (analyzer.areThereImportsWithoutExports() || !analyzer.areImportsTypesCorrect()) { exceptions.add(new BeanDefinitionValidationException( "There are severe errors while parsing contexts. See logs for details")); } if (!exceptions.isEmpty()) { for (Exception exception : exceptions) { log.error(exception.getMessage()); } throw exceptions.get(0); } DependencySorter sorter = new DependencySorter(configLocations.toArray(new String[0]), analyzer.getImports(), analyzer.getExports()); sorter.setProhibitCycles(prohibitCycles); locationsGraph = new LocationsGraph(analyzer.getImports(), analyzer.getExports()); List<String> analyzedConfigLocations = locationsGraph.filterConfigLocations(limitedLocations, sorter.sort()); log.info("ordered list of the contexts: {}", analyzedConfigLocations); return analyzedConfigLocations; } private void checkClassExist(String location, String beanName, String beanClassName) throws ClassNotFoundException { try { Class.forName(beanClassName); } catch (ClassNotFoundException e) { throw new ClassNotFoundException(MessageFormat.format( "Class not found {0} in location: {1} for bean: {2}", beanClassName, location, beanName)); } } private BeanDefinitionRegistry getBeanFactory(String location) { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader( new SimpleBeanDefinitionRegistry()); beanDefinitionReader.setResourceLoader(context); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(context)); beanDefinitionReader.loadBeanDefinitions(location); return beanDefinitionReader.getBeanFactory(); } /** * Check whether bean will be imported into other contexts. * * @param beanDefinition Definition of the bean to check. * @return <tt>true</tt> if the bean will be imported, <tt>false</tt> otherwise. */ private boolean isImport(BeanDefinition beanDefinition) { return beanDefinition.hasAttribute(ParserUtils.IMPORT_BEAN_DEF_ATTR_NAME); } /** * Check whether bean will be exported from this context into others. * * @param beanDefinition Definition of the bean to check. * @return <tt>true</tt> if the bean will be exported, <tt>false</tt> otherwise. */ private boolean isExport(BeanDefinition beanDefinition) { return beanDefinition.hasAttribute(ParserUtils.EXPORT_BEAN_DEF_ATTR_NAME); } private boolean checkForRunOnly(String beanName) { return !runOnlyServices.isEmpty() && runOnlyServices.contains(beanName); } }