1 //////////////////////////////////////////////////////////////////////////////// 2 // checkstyle: Checks Java source code for adherence to a set of rules. 3 // Copyright (C) 2001-2015 the original author or authors. 4 // 5 // This library is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 2.1 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 //////////////////////////////////////////////////////////////////////////////// 19 package com.puppycrawl.tools.checkstyle; 20 21 import com.google.common.collect.Sets; 22 import com.puppycrawl.tools.checkstyle.api.CheckstyleException; 23 import java.util.Set; 24 25 /** 26 * A factory for creating objects from package names and names. 27 * @author Rick Giles 28 * @author lkuehne 29 */ 30 class PackageObjectFactory implements ModuleFactory 31 { 32 /** a list of package names to prepend to class names */ 33 private final Set<String> packages; 34 35 /** the class loader used to load Checkstyle core and custom modules. */ 36 private final ClassLoader moduleClassLoader; 37 38 /** 39 * Creates a new <code>PackageObjectFactory</code> instance. 40 * @param packageNames the list of package names to use 41 * @param moduleClassLoader class loader used to load Checkstyle 42 * core and custom modules 43 */ 44 public PackageObjectFactory(Set<String> packageNames, 45 ClassLoader moduleClassLoader) 46 { 47 if (moduleClassLoader == null) { 48 throw new IllegalArgumentException( 49 "moduleClassLoader must not be null"); 50 } 51 52 //create a copy of the given set, but retain ordering 53 packages = Sets.newLinkedHashSet(packageNames); 54 this.moduleClassLoader = moduleClassLoader; 55 } 56 57 /** 58 * Registers a package name to use for shortName resolution. 59 * @param packageName the package name 60 */ 61 void addPackage(String packageName) 62 { 63 packages.add(packageName); 64 } 65 66 /** 67 * Creates a new instance of a class from a given name. If the name is 68 * a classname, creates an instance of the named class. Otherwise, creates 69 * an instance of a classname obtained by concatenating the given 70 * to a package name from a given list of package names. 71 * @param name the name of a class. 72 * @return the <code>Object</code> 73 * @throws CheckstyleException if an error occurs. 74 */ 75 private Object doMakeObject(String name) 76 throws CheckstyleException 77 { 78 //try name first 79 try { 80 return createObject(name); 81 } 82 catch (final CheckstyleException ex) { 83 // keep looking 84 } 85 86 //now try packages 87 for (String packageName : packages) { 88 89 final String className = packageName + name; 90 try { 91 return createObject(className); 92 } 93 catch (final CheckstyleException ex) { 94 // keep looking 95 } 96 } 97 98 throw new CheckstyleException("Unable to instantiate " + name); 99 } 100 101 /** 102 * Creates a new instance of a named class. 103 * @param className the name of the class to instantiate. 104 * @return the <code>Object</code> created by loader. 105 * @throws CheckstyleException if an error occurs. 106 */ 107 private Object createObject(String className) 108 throws CheckstyleException 109 { 110 try { 111 final Class<?> clazz = Class.forName(className, true, 112 moduleClassLoader); 113 return clazz.newInstance(); 114 } 115 catch (final ClassNotFoundException e) { 116 throw new CheckstyleException( 117 "Unable to find class for " + className, e); 118 } 119 catch (final InstantiationException e) { 120 ///CLOVER:OFF 121 throw new CheckstyleException( 122 "Unable to instantiate " + className, e); 123 ///CLOVER:ON 124 } 125 catch (final IllegalAccessException e) { 126 ///CLOVER:OFF 127 throw new CheckstyleException( 128 "Unable to instantiate " + className, e); 129 ///CLOVER:ON 130 } 131 } 132 133 /** 134 * Creates a new instance of a class from a given name, or that name 135 * concatenated with "Check". If the name is 136 * a classname, creates an instance of the named class. Otherwise, creates 137 * an instance of a classname obtained by concatenating the given name 138 * to a package name from a given list of package names. 139 * @param name the name of a class. 140 * @return the <code>Object</code> created by loader. 141 * @throws CheckstyleException if an error occurs. 142 */ 143 @Override 144 public Object createModule(String name) 145 throws CheckstyleException 146 { 147 try { 148 return doMakeObject(name); 149 } 150 catch (final CheckstyleException ex) { 151 //try again with suffix "Check" 152 try { 153 return doMakeObject(name + "Check"); 154 } 155 catch (final CheckstyleException ex2) { 156 throw new CheckstyleException( 157 "Unable to instantiate " + name, ex2); 158 } 159 } 160 } 161 }