1
2
3
4 package net.sourceforge.pmd.renderers;
5
6 import java.lang.reflect.Constructor;
7 import java.lang.reflect.InvocationTargetException;
8 import java.lang.reflect.Modifier;
9 import java.util.Collections;
10 import java.util.Map;
11 import java.util.Properties;
12 import java.util.TreeMap;
13 import java.util.logging.Level;
14 import java.util.logging.Logger;
15
16 import net.sourceforge.pmd.PropertyDescriptor;
17
18
19
20
21
22 public class RendererFactory {
23
24 private static final Logger LOG = Logger.getLogger(RendererFactory.class.getName());
25
26 public static final Map<String, Class<? extends Renderer>> REPORT_FORMAT_TO_RENDERER;
27 static {
28 Map<String, Class<? extends Renderer>> map = new TreeMap<String, Class<? extends Renderer>>();
29 map.put(CodeClimateRenderer.NAME, CodeClimateRenderer.class);
30 map.put(XMLRenderer.NAME, XMLRenderer.class);
31 map.put(IDEAJRenderer.NAME, IDEAJRenderer.class);
32 map.put(TextColorRenderer.NAME, TextColorRenderer.class);
33 map.put(TextRenderer.NAME, TextRenderer.class);
34 map.put(TextPadRenderer.NAME, TextPadRenderer.class);
35 map.put(EmacsRenderer.NAME, EmacsRenderer.class);
36 map.put(CSVRenderer.NAME, CSVRenderer.class);
37 map.put(HTMLRenderer.NAME, HTMLRenderer.class);
38 map.put(XSLTRenderer.NAME, XSLTRenderer.class);
39 map.put(YAHTMLRenderer.NAME, YAHTMLRenderer.class);
40 map.put(SummaryHTMLRenderer.NAME, SummaryHTMLRenderer.class);
41 map.put(VBHTMLRenderer.NAME, VBHTMLRenderer.class);
42 REPORT_FORMAT_TO_RENDERER = Collections.unmodifiableMap(map);
43 }
44
45
46
47
48
49
50
51 public static Renderer createRenderer(String reportFormat, Properties properties) {
52 Class<? extends Renderer> rendererClass = getRendererClass(reportFormat);
53 Constructor<? extends Renderer> constructor = getRendererConstructor(rendererClass);
54
55 Renderer renderer;
56 try {
57 if (constructor.getParameterTypes().length > 0) {
58 LOG.warning("The renderer uses a deprecated mechanism to use the properties. Please define the needed properties with this.definePropertyDescriptor(..).");
59 renderer = constructor.newInstance(properties);
60 } else {
61 renderer = constructor.newInstance();
62
63 for (PropertyDescriptor<?> prop : renderer.getPropertyDescriptors()) {
64 String value = properties.getProperty(prop.name());
65 if (value != null) {
66 @SuppressWarnings("unchecked")
67 PropertyDescriptor<Object> prop2 = (PropertyDescriptor<Object>)prop;
68 Object valueFrom = prop2.valueFrom(value);
69 renderer.setProperty(prop2, valueFrom);
70 }
71 }
72 }
73 } catch (InstantiationException e) {
74 throw new IllegalArgumentException("Unable to construct report renderer class: " + e.getLocalizedMessage());
75 } catch (IllegalAccessException e) {
76 throw new IllegalArgumentException("Unable to construct report renderer class: " + e.getLocalizedMessage());
77 } catch (InvocationTargetException e) {
78 throw new IllegalArgumentException("Unable to construct report renderer class: "
79 + e.getTargetException().getLocalizedMessage());
80 }
81
82 if (REPORT_FORMAT_TO_RENDERER.containsKey(reportFormat) && !reportFormat.equals(renderer.getName())) {
83 if (LOG.isLoggable(Level.WARNING)) {
84 LOG.warning("Report format '" + reportFormat + "' is deprecated, and has been replaced with '"
85 + renderer.getName()
86 + "'. Future versions of PMD will remove support for this deprecated Report format usage.");
87 }
88 }
89 return renderer;
90 }
91
92 @SuppressWarnings("unchecked")
93 private static Class<? extends Renderer> getRendererClass(String reportFormat) {
94 Class<? extends Renderer> rendererClass = REPORT_FORMAT_TO_RENDERER.get(reportFormat);
95
96
97 if (rendererClass == null && !"".equals(reportFormat)) {
98 try {
99 Class<?> clazz = Class.forName(reportFormat);
100 if (!Renderer.class.isAssignableFrom(clazz)) {
101 throw new IllegalArgumentException("Custom report renderer class does not implement the "
102 + Renderer.class.getName() + " interface.");
103 } else {
104 rendererClass = (Class<? extends Renderer>) clazz;
105 }
106 } catch (ClassNotFoundException e) {
107 throw new IllegalArgumentException("Can't find the custom format " + reportFormat + ": "
108 + e);
109 }
110 }
111 return rendererClass;
112 }
113
114 private static Constructor<? extends Renderer> getRendererConstructor(Class<? extends Renderer> rendererClass) {
115 Constructor<? extends Renderer> constructor = null;
116
117
118 try {
119 constructor = rendererClass.getConstructor(Properties.class);
120 if (!Modifier.isPublic(constructor.getModifiers())) {
121 constructor = null;
122 }
123 } catch (NoSuchMethodException e) {
124
125 }
126
127
128 try {
129 constructor = rendererClass.getConstructor();
130 if (!Modifier.isPublic(constructor.getModifiers())) {
131 constructor = null;
132 }
133 } catch (NoSuchMethodException e2) {
134
135 }
136
137 if (constructor == null) {
138 throw new IllegalArgumentException(
139 "Unable to find either a public java.util.Properties or no-arg constructors for Renderer class: "
140 + rendererClass.getName());
141 }
142 return constructor;
143 }
144 }