1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2014 Oliver Burn
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 }