1
24 package net.sf.jasperreports.compilers;
25
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.ConcurrentHashMap;
30
31 import net.sf.jasperreports.annotations.properties.Property;
32 import net.sf.jasperreports.annotations.properties.PropertyScope;
33 import net.sf.jasperreports.engine.JRPropertiesUtil;
34 import net.sf.jasperreports.engine.JRPropertiesUtil.PropertySuffix;
35 import net.sf.jasperreports.engine.JRRuntimeException;
36 import net.sf.jasperreports.engine.JasperReportsContext;
37 import net.sf.jasperreports.engine.util.ClassLoaderFilter;
38 import net.sf.jasperreports.functions.FunctionsBundle;
39 import net.sf.jasperreports.functions.FunctionsUtil;
40 import net.sf.jasperreports.properties.PropertyConstants;
41
42
45 public class ReportClassFilter implements ClassLoaderFilter
46 {
47
48 @Property(
49 category = PropertyConstants.CATEGORY_FILL,
50 defaultValue = "false",
51 scopes = {PropertyScope.CONTEXT},
52 sinceVersion = PropertyConstants.VERSION_6_13_0,
53 valueType = Boolean.class
54 )
55 public static final String PROPERTY_PREFIX_CLASS_FILTER_ENABLED =
56 JRPropertiesUtil.PROPERTY_PREFIX + "report.class.filter.enabled";
57
58 @Property(
59 category = PropertyConstants.CATEGORY_FILL,
60 scopes = {PropertyScope.CONTEXT},
61 sinceVersion = PropertyConstants.VERSION_6_13_0,
62 name = "net.sf.jasperreports.report.class.whitelist.{arbitrary_name}"
63 )
64 public static final String PROPERTY_PREFIX_CLASS_WHITELIST =
65 JRPropertiesUtil.PROPERTY_PREFIX + "report.class.whitelist.";
66
67 public static final String EXCEPTION_MESSAGE_KEY_CLASS_NOT_VISIBLE = "compilers.class.not.visible";
68
69 private static void addHardcodedWhitelist(StandardReportClassWhitelist whitelist)
70 {
71 whitelist.addClass("java.lang.Boolean");
72 whitelist.addClass("java.lang.String");
73 whitelist.addClass("java.lang.StringBuffer");
74 whitelist.addClass("java.lang.StringBuilder");
75 whitelist.addClass("java.lang.Character");
76 whitelist.addClass("java.lang.Byte");
77 whitelist.addClass("java.lang.Short");
78 whitelist.addClass("java.lang.Integer");
79 whitelist.addClass("java.lang.Long");
80 whitelist.addClass("java.lang.Float");
81 whitelist.addClass("java.lang.Double");
82 whitelist.addClass("java.lang.Math");
83 }
84
85 private boolean filterEnabled;
86 private List<ReportClassWhitelist> whitelists;
87
88 private Map<String, Boolean> visibilityCache = new ConcurrentHashMap<String, Boolean>();
89
90 public ReportClassFilter(JasperReportsContext jasperReportsContext)
91 {
92 JRPropertiesUtil properties = JRPropertiesUtil.getInstance(jasperReportsContext);
93 filterEnabled = properties.getBooleanProperty(PROPERTY_PREFIX_CLASS_FILTER_ENABLED);
94 if (filterEnabled)
95 {
96 whitelists = new ArrayList<>();
97
98 StandardReportClassWhitelist whitelist = new StandardReportClassWhitelist();
99 addHardcodedWhitelist(whitelist);
100 loadPropertiesWhitelist(properties, whitelist);
101 loadFunctionsWhitelist(jasperReportsContext, whitelist);
102 whitelists.add(whitelist);
103
104 List<ReportClassWhitelist> extensionWhitelists = jasperReportsContext.getExtensions(
105 ReportClassWhitelist.class);
106 whitelists.addAll(extensionWhitelists);
107 }
108 }
109
110 private static void loadPropertiesWhitelist(JRPropertiesUtil propertiesUtil,
111 StandardReportClassWhitelist whitelist)
112 {
113 List<PropertySuffix> properties = propertiesUtil.getProperties(PROPERTY_PREFIX_CLASS_WHITELIST);
114 for (PropertySuffix propertySuffix : properties)
115 {
116 String whitelistString = propertySuffix.getValue();
117 whitelist.addWhitelist(whitelistString);
118 }
119 }
120
121 private static void loadFunctionsWhitelist(JasperReportsContext jasperReportsContext,
122 StandardReportClassWhitelist whitelist)
123 {
124 FunctionsUtil functionsUtil = FunctionsUtil.getInstance(jasperReportsContext);
125 List<FunctionsBundle> functionBundles = functionsUtil.getAllFunctionBundles();
126 for (FunctionsBundle functionsBundle : functionBundles)
127 {
128 List<Class<?>> functionClasses = functionsBundle.getFunctionClasses();
129 for (Class<?> functionClass : functionClasses)
130 {
131 whitelist.addClass(functionClass.getName());
132 }
133 }
134 }
135
136 public boolean isFilteringEnabled()
137 {
138 return filterEnabled;
139 }
140
141 @Override
142 public void checkClassVisibility(String className) throws JRRuntimeException
143 {
144 boolean visible = isClassVisible(className);
145 if (!visible)
146 {
147 throw new JRRuntimeException(EXCEPTION_MESSAGE_KEY_CLASS_NOT_VISIBLE, new Object[] {className});
148 }
149 }
150
151 public boolean isClassVisible(String className)
152 {
153 Boolean visible = visibilityCache.get(className);
154 if (visible == null)
155 {
156 visible = visible(className);
157 visibilityCache.put(className, visible);
158 }
159 return visible;
160 }
161
162 protected boolean visible(String className)
163 {
164 boolean visible;
165 if (filterEnabled)
166 {
167 visible = false;
168 for (ReportClassWhitelist whitelist : whitelists)
169 {
170 if (whitelist.includesClass(className))
171 {
172 visible = true;
173 break;
174 }
175 }
176 }
177 else
178 {
179 visible = true;
180 }
181 return visible;
182 }
183
184 }
185