View Javadoc
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 &quot;Check&quot;. 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 }