1
18 package net.bull.javamelody.internal.common;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.net.InetAddress;
26 import java.net.MalformedURLException;
27 import java.net.URL;
28 import java.net.UnknownHostException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Properties;
36 import java.util.TreeMap;
37
38 import javax.servlet.FilterConfig;
39 import javax.servlet.ServletContext;
40
41 import net.bull.javamelody.Parameter;
42 import net.bull.javamelody.internal.model.TransportFormat;
43
44
48 public final class Parameters {
49 public static final String PARAMETER_SYSTEM_PREFIX = "javamelody.";
50 public static final File TEMPORARY_DIRECTORY = new File(System.getProperty("java.io.tmpdir"));
51 public static final String JAVA_VERSION = System.getProperty("java.version");
52 public static final String JAVAMELODY_VERSION = getJavaMelodyVersion();
53
54 private static final String DEFAULT_MONITORING_PATH = "/monitoring";
55
56 private static final int DEFAULT_RESOLUTION_SECONDS = 60;
57
58 private static final String DEFAULT_DIRECTORY = "javamelody";
59
60 private static final String COLLECTOR_APPLICATIONS_FILENAME = "applications.properties";
61 private static final boolean PDF_ENABLED = computePdfEnabled();
62 private static Map<String, List<URL>> urlsByApplications;
63 private static Map<String, List<String>> applicationsByAggregationApplications;
64
65 private static FilterConfig filterConfig;
66 private static ServletContext servletContext;
67 private static String lastConnectUrl;
68 private static Properties lastConnectInfo;
69 private static boolean dnsLookupsDisabled;
70
71 private Parameters() {
72 super();
73 }
74
75 public static void initialize(FilterConfig config) {
76 filterConfig = config;
77 if (config != null) {
78 final ServletContext context = config.getServletContext();
79 initialize(context);
80 }
81 }
82
83 public static void initialize(ServletContext context) {
84 if ("1.6".compareTo(JAVA_VERSION) > 0) {
85 throw new IllegalStateException(
86 "La version java doit être 1.6 au minimum et non " + JAVA_VERSION);
87 }
88 servletContext = context;
89
90 dnsLookupsDisabled = Parameter.DNS_LOOKUPS_DISABLED.getValueAsBoolean();
91 }
92
93 public static void initJdbcDriverParameters(String connectUrl, Properties connectInfo) {
94 lastConnectUrl = connectUrl;
95 lastConnectInfo = connectInfo;
96 }
97
98
101 public static ServletContext getServletContext() {
102 assert servletContext != null;
103 return servletContext;
104 }
105
106 public static String getLastConnectUrl() {
107 return lastConnectUrl;
108 }
109
110 public static Properties getLastConnectInfo() {
111 return lastConnectInfo;
112 }
113
114
118 public static Map<String, List<URL>> getCollectorUrlsByApplications() throws IOException {
119 if (urlsByApplications == null) {
120 readCollectorApplications();
121 }
122 return Collections.unmodifiableMap(urlsByApplications);
123 }
124
125 public static Map<String, List<String>> getApplicationsByAggregationApplication()
126 throws IOException {
127 if (applicationsByAggregationApplications == null) {
128 readCollectorApplications();
129 }
130 return Collections.unmodifiableMap(applicationsByAggregationApplications);
131 }
132
133 public static void addCollectorApplication(String application, List<URL> urls)
134 throws IOException {
135 assert application != null;
136 assert urls != null && !urls.isEmpty();
137
138 getCollectorUrlsByApplications();
139
140 urlsByApplications.put(application, urls);
141 writeCollectorApplications();
142 }
143
144 public static void addCollectorAggregationApplication(String aggregationApplication,
145 List<String> aggregatedApplications) throws IOException {
146 assert aggregationApplication != null;
147 assert aggregatedApplications != null && !aggregatedApplications.isEmpty();
148
149 getCollectorUrlsByApplications();
150
151 applicationsByAggregationApplications.put(aggregationApplication, aggregatedApplications);
152 writeCollectorApplications();
153 }
154
155 public static void removeCollectorApplication(String application) throws IOException {
156 assert application != null;
157
158 getCollectorUrlsByApplications();
159
160 if (urlsByApplications.containsKey(application)) {
161 urlsByApplications.remove(application);
162 } else {
163 applicationsByAggregationApplications.remove(application);
164 }
165 synchronizeAggregationApplications();
166 writeCollectorApplications();
167 }
168
169 private static void writeCollectorApplications() throws IOException {
170 final Properties properties = new Properties();
171 final String monitoringPath = getMonitoringPath();
172 for (final Map.Entry<String, List<URL>> entry : urlsByApplications.entrySet()) {
173 final List<URL> urls = entry.getValue();
174 assert urls != null && !urls.isEmpty();
175 final StringBuilder sb = new StringBuilder();
176 for (final URL url : urls) {
177 final String urlString = url.toString();
178
179 final String webappUrl = urlString.substring(0,
180 urlString.lastIndexOf(monitoringPath));
181 if (webappUrl.indexOf(',') != -1) {
182 throw new IOException("The URL should not contain a comma.");
183 }
184 sb.append(webappUrl).append(',');
185 }
186 sb.delete(sb.length() - 1, sb.length());
187 properties.put(entry.getKey(), sb.toString());
188 }
189 for (final Map.Entry<String, List<String>> entry : applicationsByAggregationApplications
190 .entrySet()) {
191 final List<String> applications = entry.getValue();
192 final StringBuilder sb = new StringBuilder();
193 for (final String application : applications) {
194 if (application.indexOf(',') != -1) {
195 throw new IOException("The application name should not contain a comma.");
196 }
197 sb.append(application).append(',');
198 }
199 sb.delete(sb.length() - 1, sb.length());
200 properties.put(entry.getKey(), sb.toString());
201 }
202 final File collectorApplicationsFile = getCollectorApplicationsFile();
203 final File directory = collectorApplicationsFile.getParentFile();
204 if (!directory.mkdirs() && !directory.exists()) {
205 throw new IOException("JavaMelody directory can't be created: " + directory.getPath());
206 }
207 try (FileOutputStream output = new FileOutputStream(collectorApplicationsFile)) {
208 properties.store(output, "urls of the applications to monitor");
209 }
210 }
211
212 private static void readCollectorApplications() throws IOException {
213
214
215
216
217
218
219
220 final Map<String, List<URL>> applications = new TreeMap<>();
221 final Map<String, List<String>> aggregationApplications = new TreeMap<>();
222 final File file = getCollectorApplicationsFile();
223 if (file.exists()) {
224 final Properties properties = new Properties();
225 try (FileInputStream input = new FileInputStream(file)) {
226 properties.load(input);
227 }
228 @SuppressWarnings("unchecked")
229 final List<String> propertyNames = (List<String>) Collections
230 .list(properties.propertyNames());
231 for (final String property : propertyNames) {
232 final String value = String.valueOf(properties.get(property));
233 if (value.startsWith("http")) {
234 applications.put(property, parseUrls(value));
235 } else {
236 aggregationApplications.put(property,
237 new ArrayList<>(Arrays.asList(value.split(","))));
238 }
239 }
240 }
241 urlsByApplications = applications;
242 applicationsByAggregationApplications = aggregationApplications;
243
244 synchronizeAggregationApplications();
245 }
246
247 private static void synchronizeAggregationApplications() {
248 for (final Iterator<List<String>> it1 = applicationsByAggregationApplications.values()
249 .iterator(); it1.hasNext();) {
250 final List<String> aggregatedApplications = it1.next();
251 for (final Iterator<String> it2 = aggregatedApplications.iterator(); it2.hasNext();) {
252 final String aggregatedApplication = it2.next();
253 if (!urlsByApplications.containsKey(aggregatedApplication)
254 && !applicationsByAggregationApplications
255 .containsKey(aggregatedApplication)) {
256
257 it2.remove();
258 }
259 }
260 if (aggregatedApplications.isEmpty()) {
261
262 it1.remove();
263 }
264 }
265 }
266
267 public static File getCollectorApplicationsFile() {
268 return new File(getStorageDirectory(""), COLLECTOR_APPLICATIONS_FILENAME);
269 }
270
271 public static List<URL> parseUrls(String value) throws MalformedURLException {
272
273 final TransportFormat transportFormat;
274 if (Parameter.TRANSPORT_FORMAT.getValue() == null) {
275 transportFormat = TransportFormat.SERIALIZED;
276 } else {
277 transportFormat = TransportFormat
278 .valueOfIgnoreCase(Parameter.TRANSPORT_FORMAT.getValue());
279 }
280 final String suffix = getMonitoringPath() + "?collector=stop&format="
281 + transportFormat.getCode();
282
283 final String[] urlsArray = value.split(",");
284 final List<URL> urls = new ArrayList<>(urlsArray.length);
285 for (final String s : urlsArray) {
286 String s2 = s.trim();
287 while (s2.endsWith("/")) {
288 s2 = s2.substring(0, s2.length() - 1);
289 }
290 final URL url = new URL(s2 + suffix);
291 urls.add(url);
292 }
293 return urls;
294 }
295
296 public static String getMonitoringPath() {
297 final String parameterValue = Parameter.MONITORING_PATH.getValue();
298 if (parameterValue == null) {
299 return DEFAULT_MONITORING_PATH;
300 }
301 return parameterValue;
302 }
303
304
307 public static String getHostName() {
308 if (dnsLookupsDisabled) {
309 return "localhost";
310 }
311
312 try {
313 return InetAddress.getLocalHost().getHostName();
314 } catch (final UnknownHostException ex) {
315 return "unknown";
316 }
317 }
318
319
322 public static String getHostAddress() {
323 if (dnsLookupsDisabled) {
324 return "127.0.0.1";
325 }
326
327 try {
328 return InetAddress.getLocalHost().getHostAddress();
329 } catch (final UnknownHostException ex) {
330 return "unknown";
331 }
332 }
333
334
338 public static String getResourcePath(String fileName) {
339 return "/net/bull/javamelody/resource/" + fileName;
340 }
341
342
345 public static int getResolutionSeconds() {
346 final String param = Parameter.RESOLUTION_SECONDS.getValue();
347 if (param != null) {
348
349 final int result = Integer.parseInt(param);
350 if (result <= 0) {
351 throw new IllegalStateException(
352 "The parameter resolution-seconds should be > 0 (between 60 and 600 recommended)");
353 }
354 return result;
355 }
356 return DEFAULT_RESOLUTION_SECONDS;
357 }
358
359
363 public static File getStorageDirectory(String application) {
364 final String param = Parameter.STORAGE_DIRECTORY.getValue();
365 final String dir;
366 if (param == null) {
367 dir = DEFAULT_DIRECTORY;
368 } else {
369 dir = param;
370 }
371
372
373
374
375 final String directory;
376 if (!dir.isEmpty() && new File(dir).isAbsolute()) {
377 directory = dir;
378 } else {
379 directory = TEMPORARY_DIRECTORY.getPath() + '/' + dir;
380 }
381 if (servletContext != null) {
382 return new File(directory + '/' + application);
383 }
384 return new File(directory);
385 }
386
387
391 public static boolean isNoDatabase() {
392 return Parameter.NO_DATABASE.getValueAsBoolean();
393 }
394
395
399 public static boolean isSystemActionsEnabled() {
400 final String parameter = Parameter.SYSTEM_ACTIONS_ENABLED.getValue();
401 return parameter == null || Boolean.parseBoolean(parameter);
402 }
403
404 public static boolean isPdfEnabled() {
405 return PDF_ENABLED;
406 }
407
408 private static boolean computePdfEnabled() {
409 try {
410 Class.forName("com.lowagie.text.Document");
411 return true;
412 } catch (final ClassNotFoundException e) {
413 return false;
414 }
415 }
416
417
425 public static boolean isCounterHidden(String counterName) {
426 final String displayedCounters = Parameter.DISPLAYED_COUNTERS.getValue();
427 if (displayedCounters == null) {
428 return false;
429 }
430 for (final String displayedCounter : displayedCounters.split(",")) {
431 final String displayedCounterName = displayedCounter.trim();
432 if (counterName.equalsIgnoreCase(displayedCounterName)) {
433 return false;
434 }
435 }
436 return true;
437 }
438
439
442 public static String getCurrentApplication() {
443
444 final String applicationName = Parameter.APPLICATION_NAME.getValue();
445 if (applicationName != null) {
446 return applicationName;
447 }
448 if (servletContext != null) {
449
450
451
452
453 return getContextPath(servletContext) + '_' + getHostName();
454 }
455 return null;
456 }
457
458 public static String getContextPath(ServletContext context) {
459
460
461
462
463 if (context.getMajorVersion() == 2 && context.getMinorVersion() >= 5
464 || context.getMajorVersion() > 2) {
465
466 return context.getContextPath();
467 }
468 final URL webXmlUrl;
469 try {
470 webXmlUrl = context.getResource("/WEB-INF/web.xml");
471 } catch (final MalformedURLException e) {
472 throw new IllegalStateException(e);
473 }
474 String contextPath = webXmlUrl.toExternalForm();
475 contextPath = contextPath.substring(0, contextPath.indexOf("/WEB-INF/web.xml"));
476 final int indexOfWar = contextPath.indexOf(".war");
477 if (indexOfWar > 0) {
478 contextPath = contextPath.substring(0, indexOfWar);
479 }
480
481
482 if (contextPath.startsWith("jndi:/localhost")) {
483 contextPath = contextPath.substring("jndi:/localhost".length());
484 }
485 final int lastIndexOfSlash = contextPath.lastIndexOf('/');
486 if (lastIndexOfSlash != -1) {
487 contextPath = contextPath.substring(lastIndexOfSlash);
488 }
489 return contextPath;
490 }
491
492 private static String getJavaMelodyVersion() {
493 final InputStream inputStream = Parameters.class
494 .getResourceAsStream("/JAVAMELODY-VERSION.properties");
495 if (inputStream == null) {
496 return null;
497 }
498
499 final Properties properties = new Properties();
500 try {
501 try {
502 properties.load(inputStream);
503 return properties.getProperty("version");
504 } finally {
505 inputStream.close();
506 }
507 } catch (final IOException e) {
508 return e.toString();
509 }
510 }
511
512
521 public static String getParameterValue(Parameter parameter) {
522 assert parameter != null;
523 final String name = parameter.getCode();
524 return getParameterValueByName(name);
525 }
526
527 public static String getParameterValueByName(String parameterName) {
528 assert parameterName != null;
529 final String globalName = PARAMETER_SYSTEM_PREFIX + parameterName;
530 String result = System.getProperty(globalName);
531 if (result != null) {
532 return result;
533 }
534 if (servletContext != null) {
535 result = servletContext.getInitParameter(globalName);
536 if (result != null) {
537 return result;
538 }
539
540 final Object attribute = servletContext.getAttribute(globalName);
541 if (attribute instanceof String) {
542 return (String) attribute;
543 }
544 }
545 if (filterConfig != null) {
546 return filterConfig.getInitParameter(parameterName);
547 }
548 return null;
549 }
550 }
551