1
2
3
4
5
6
7
8
9
10
11 package psiprobe.beans;
12
13 import jakarta.inject.Inject;
14 import jakarta.servlet.ServletContext;
15
16 import java.io.File;
17 import java.io.Serializable;
18 import java.lang.reflect.InvocationTargetException;
19 import java.lang.reflect.Method;
20 import java.nio.file.Path;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.catalina.Context;
29 import org.apache.catalina.Loader;
30 import org.apache.commons.lang3.reflect.MethodUtils;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.annotation.Autowired;
34 import org.springframework.util.ClassUtils;
35
36 import psiprobe.model.Application;
37 import psiprobe.model.DisconnectedLogDestination;
38 import psiprobe.tools.ApplicationUtils;
39 import psiprobe.tools.Instruments;
40 import psiprobe.tools.logging.FileLogAccessor;
41 import psiprobe.tools.logging.LogDestination;
42 import psiprobe.tools.logging.catalina.CatalinaLoggerAccessor;
43 import psiprobe.tools.logging.commons.CommonsLoggerAccessor;
44 import psiprobe.tools.logging.jdk.Jdk14LoggerAccessor;
45 import psiprobe.tools.logging.jdk.Jdk14ManagerAccessor;
46 import psiprobe.tools.logging.log4j.Log4JLoggerAccessor;
47 import psiprobe.tools.logging.log4j.Log4JManagerAccessor;
48 import psiprobe.tools.logging.log4j2.Log4J2AppenderAccessor;
49 import psiprobe.tools.logging.log4j2.Log4J2LoggerConfigAccessor;
50 import psiprobe.tools.logging.log4j2.Log4J2LoggerContextAccessor;
51 import psiprobe.tools.logging.log4j2.Log4J2WebLoggerContextUtilsAccessor;
52 import psiprobe.tools.logging.logback.LogbackFactoryAccessor;
53 import psiprobe.tools.logging.logback.LogbackLoggerAccessor;
54 import psiprobe.tools.logging.logback13.Logback13FactoryAccessor;
55 import psiprobe.tools.logging.logback13.Logback13LoggerAccessor;
56 import psiprobe.tools.logging.slf4jlogback.TomcatSlf4jLogbackFactoryAccessor;
57 import psiprobe.tools.logging.slf4jlogback.TomcatSlf4jLogbackLoggerAccessor;
58 import psiprobe.tools.logging.slf4jlogback13.TomcatSlf4jLogback13FactoryAccessor;
59 import psiprobe.tools.logging.slf4jlogback13.TomcatSlf4jLogback13LoggerAccessor;
60
61
62
63
64 public class LogResolverBean {
65
66
67 private static final Logger logger = LoggerFactory.getLogger(LogResolverBean.class);
68
69
70 @Inject
71 private ContainerWrapperBean containerWrapper;
72
73
74 private List<String> stdoutFiles = new ArrayList<>();
75
76
77
78
79
80
81 public List<String> getStdoutFiles() {
82 return stdoutFiles;
83 }
84
85
86
87
88
89
90 @Autowired
91 public void setStdoutFiles(List<String> stdoutFiles) {
92 logger.info("stdoutFiles {}", stdoutFiles);
93 this.stdoutFiles = stdoutFiles;
94 }
95
96
97
98
99
100
101
102
103 public List<LogDestination> getLogDestinations(boolean all) {
104 List<LogDestination> allAppenders = getAllLogDestinations();
105
106 if (allAppenders.isEmpty()) {
107 return List.of();
108 }
109
110
111
112
113 List<LogDestination> uniqueList = new LinkedList<>();
114 AbstractLogComparator cmp = new LogDestinationComparator(all);
115
116 allAppenders.sort(cmp);
117 for (LogDestination dest : allAppenders) {
118 if (Collections.binarySearch(uniqueList, dest, cmp) < 0
119 && (all || dest.getFile() == null || dest.getFile().exists())) {
120 uniqueList.add(new DisconnectedLogDestination().builder(dest));
121 }
122 }
123 return uniqueList;
124 }
125
126
127
128
129
130
131
132
133 public List<LogDestination> getLogSources(File logFile) {
134 List<LogDestination> filtered = new LinkedList<>();
135 List<LogDestination> sources = getLogSources();
136 for (LogDestination dest : sources) {
137 if (logFile.equals(dest.getFile())) {
138 filtered.add(dest);
139 }
140 }
141 return filtered;
142 }
143
144
145
146
147
148
149 public List<LogDestination> getLogSources() {
150 List<LogDestination> sources = new LinkedList<>();
151
152 List<LogDestination> allAppenders = getAllLogDestinations();
153 if (!allAppenders.isEmpty()) {
154 AbstractLogComparator cmp = new LogSourceComparator();
155
156 allAppenders.sort(cmp);
157 for (LogDestination dest : allAppenders) {
158 if (Collections.binarySearch(sources, dest, cmp) < 0) {
159 sources.add(new DisconnectedLogDestination().builder(dest));
160 }
161 }
162 }
163 return sources;
164 }
165
166
167
168
169
170
171 private List<LogDestination> getAllLogDestinations() {
172 if (!Instruments.isInitialized()) {
173 return List.of();
174 }
175
176 List<LogDestination> allAppenders = new ArrayList<>();
177
178
179
180
181 ClassLoader cl2 = Thread.currentThread().getContextClassLoader().getParent();
182 while (cl2 != null) {
183 interrogateClassLoader(cl2, null, allAppenders);
184 cl2 = cl2.getParent();
185 }
186
187
188
189
190 interrogateStdOutFiles(allAppenders);
191
192
193
194
195 List<Context> contexts = containerWrapper.getTomcatContainer().findContexts();
196 for (Context ctx : contexts) {
197 interrogateContext(ctx, allAppenders);
198 }
199
200 return allAppenders;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215 public LogDestination getLogDestination(String logType, String webapp, boolean context,
216 boolean root, String logName, String logIndex) {
217
218
219 List<String> loggers = new ArrayList<>();
220 loggers.add("jdk");
221 loggers.add("log4j");
222 loggers.add("log4j2");
223 loggers.add("logback");
224 loggers.add("logback13");
225 loggers.add("tomcatSlf4jLogback");
226 loggers.add("tomcatSlf4jLogback13");
227
228 Context ctx = null;
229 Application application = null;
230 if (webapp != null) {
231 ctx = containerWrapper.getTomcatContainer().findContext(webapp);
232 if (ctx != null) {
233 application = ApplicationUtils.getApplication(ctx, containerWrapper);
234 }
235 }
236
237 LogDestination result = null;
238 if (logName != null && "stdout".equals(logType)) {
239 result = getStdoutLogDestination(logName);
240 } else if (ctx != null && "catalina".equals(logType)) {
241 result = getCatalinaLogDestination(ctx, application);
242 } else if (logIndex != null && loggers.contains(logType)) {
243 if (context && ctx != null && !"log4j2".equals(logType)) {
244 result = getCommonsLogDestination(ctx, application, logIndex);
245 } else if (ctx != null && "log4j2".equals(logType)) {
246 result = getLog4J2LogDestination(ctx, application, root, logName, logIndex);
247 } else {
248 ClassLoader cl;
249 ClassLoader prevCl = null;
250 if (ctx != null) {
251 Loader ctxLoader = ctx.getLoader();
252 cl = ctxLoader != null ? ctxLoader.getClassLoader() : null;
253 if (cl != null) {
254 prevCl = ClassUtils.overrideThreadContextClassLoader(cl);
255 } else {
256 cl = Thread.currentThread().getContextClassLoader().getParent();
257 }
258 } else {
259 cl = Thread.currentThread().getContextClassLoader().getParent();
260 }
261 try {
262 if (root || logName != null) {
263 if ("jdk".equals(logType)) {
264 result = getJdk14LogDestination(cl, application, root, logName, logIndex);
265 } else if ("log4j".equals(logType)) {
266 result = getLog4JLogDestination(cl, application, root, logName, logIndex);
267 } else if ("logback".equals(logType)) {
268 result = getLogbackLogDestination(cl, application, root, logName, logIndex);
269 } else if ("logback13".equals(logType)) {
270 result = getLogback13LogDestination(cl, application, root, logName, logIndex);
271 } else if ("tomcatSlf4jLogback".equals(logType)) {
272 result = getLogbackTomcatJuliLogDestination(cl, application, root, logName, logIndex);
273 } else if ("tomcatSlf4jLogback13".equals(logType)) {
274 result =
275 getLogback13TomcatJuliLogDestination(cl, application, root, logName, logIndex);
276 }
277 }
278 } finally {
279 if (prevCl != null) {
280 ClassUtils.overrideThreadContextClassLoader(prevCl);
281 }
282 }
283 }
284 }
285 return result;
286 }
287
288
289
290
291
292
293
294 private void interrogateContext(Context ctx, List<LogDestination> allAppenders) {
295 Application application = ApplicationUtils.getApplication(ctx, containerWrapper);
296 Loader loader = ctx.getLoader();
297 if (loader == null) {
298 logger.debug("Context {} has no loader, skipping classloader interrogation", ctx.getName());
299 return;
300 }
301 ClassLoader cl = loader.getClassLoader();
302 Object contextLogger = ctx.getLogger();
303 if (contextLogger != null) {
304 if (contextLogger.getClass().getName().startsWith("org.apache.commons.logging")) {
305 CommonsLoggerAccessor commonsAccessor = new CommonsLoggerAccessor();
306 commonsAccessor.setTarget(contextLogger);
307 commonsAccessor.setApplication(application);
308 allAppenders.addAll(commonsAccessor.getDestinations());
309 } else if (contextLogger.getClass().getName().startsWith("org.apache.catalina.logger")) {
310 CatalinaLoggerAccessor catalinaAccessor = new CatalinaLoggerAccessor();
311 catalinaAccessor.setApplication(application);
312 catalinaAccessor.setTarget(contextLogger);
313 allAppenders.add(catalinaAccessor);
314 }
315
316 ServletContext servletContext = ctx.getServletContext();
317 try {
318 Log4J2LoggerContextAccessor loggerContextAccessor = null;
319 try {
320 Log4J2WebLoggerContextUtilsAccessor webLoggerContextUtilsAccessor =
321 new Log4J2WebLoggerContextUtilsAccessor(cl);
322 loggerContextAccessor = webLoggerContextUtilsAccessor.getWebLoggerContext(servletContext);
323 } catch (Exception e) {
324 logger.debug("Log4J2LoggerContextAccessor instantiation failed", e);
325 }
326 List<Object> loggerContexts = getLoggerContexts(cl);
327 for (Object loggerContext : loggerContexts) {
328 Map<String, Object> loggerConfigs = getLoggerConfigs(loggerContext);
329 for (Object loggerConfig : loggerConfigs.values()) {
330 Log4J2LoggerConfigAccessor logConfigAccessor = new Log4J2LoggerConfigAccessor();
331 logConfigAccessor.setTarget(loggerConfig);
332 logConfigAccessor.setApplication(application);
333 logConfigAccessor.setContext(true);
334 logConfigAccessor.setLoggerContext(loggerContextAccessor);
335 allAppenders.addAll(logConfigAccessor.getAppenders());
336 }
337 }
338 } catch (Exception e) {
339 logger.debug("getting appenders failed", e);
340 }
341 }
342
343 if (application.isAvailable()) {
344 ClassLoader prevCl = ClassUtils.overrideThreadContextClassLoader(cl);
345 try {
346 interrogateClassLoader(cl, application, allAppenders);
347 } catch (Exception e) {
348 logger.error(
349 "Could not interrogate classloader loggers for {}. Enable debug logging to see the trace stack",
350 ctx.getName());
351 logger.debug("", e);
352 } finally {
353 if (prevCl != null) {
354 ClassUtils.overrideThreadContextClassLoader(prevCl);
355 }
356 }
357 }
358 }
359
360
361
362
363
364
365
366
367 private void interrogateClassLoader(ClassLoader cl, Application application,
368 List<LogDestination> appenders) {
369
370 String applicationName =
371 application != null ? "application \"" + application.getName() + "\"" : "server";
372
373
374 try {
375 Jdk14ManagerAccessor jdk14accessor = new Jdk14ManagerAccessor(cl);
376 jdk14accessor.setApplication(application);
377 appenders.addAll(jdk14accessor.getHandlers());
378 } catch (Exception e) {
379 logger.debug("Could not resolve JDK loggers for '{}'", applicationName, e);
380 }
381
382
383 try {
384 Log4JManagerAccessor log4JAccessor = new Log4JManagerAccessor(cl);
385 log4JAccessor.setApplication(application);
386 appenders.addAll(log4JAccessor.getAppenders());
387 } catch (Exception e) {
388 logger.debug("Could not resolve log4j loggers for '{}'", applicationName, e);
389 }
390
391
392 try {
393 LogbackFactoryAccessor logbackAccessor = new LogbackFactoryAccessor(cl);
394 logbackAccessor.setApplication(application);
395 appenders.addAll(logbackAccessor.getAppenders());
396 } catch (Exception e) {
397 logger.debug("Could not resolve logback loggers for '{}'", applicationName, e);
398 }
399
400
401 try {
402 Logback13FactoryAccessor logback13Accessor = new Logback13FactoryAccessor(cl);
403 logback13Accessor.setApplication(application);
404 appenders.addAll(logback13Accessor.getAppenders());
405 } catch (Exception e) {
406 logger.debug("Could not resolve logback 1.3 loggers for '{}'", applicationName, e);
407 }
408
409
410 try {
411 TomcatSlf4jLogbackFactoryAccessor tomcatSlf4jLogbackAccessor =
412 new TomcatSlf4jLogbackFactoryAccessor(cl);
413 tomcatSlf4jLogbackAccessor.setApplication(application);
414 appenders.addAll(tomcatSlf4jLogbackAccessor.getAppenders());
415 } catch (Exception e) {
416 logger.debug("Could not resolve tomcat-slf4j-logback loggers for '{}'", applicationName, e);
417 }
418
419
420 try {
421 TomcatSlf4jLogback13FactoryAccessor tomcatSlf4jLogback13Accessor =
422 new TomcatSlf4jLogback13FactoryAccessor(cl);
423 tomcatSlf4jLogback13Accessor.setApplication(application);
424 appenders.addAll(tomcatSlf4jLogback13Accessor.getAppenders());
425 } catch (Exception e) {
426 logger.debug("Could not resolve tomcat-slf4j-logback 1.3 loggers for '{}'", applicationName,
427 e);
428 }
429 }
430
431
432
433
434
435
436 private void interrogateStdOutFiles(List<LogDestination> appenders) {
437 for (String fileName : stdoutFiles) {
438 FileLogAccessor fla = resolveStdoutLogDestination(fileName);
439 if (fla != null) {
440 appenders.add(fla);
441 }
442 }
443 }
444
445
446
447
448
449
450
451
452 private LogDestination getStdoutLogDestination(String logName) {
453 for (String fileName : stdoutFiles) {
454 if (fileName.equals(logName)) {
455 FileLogAccessor fla = resolveStdoutLogDestination(fileName);
456 if (fla != null) {
457 return fla;
458 }
459 }
460 }
461 return null;
462 }
463
464
465
466
467
468
469
470
471 protected FileLogAccessor resolveStdoutLogDestination(String fileName) {
472 File stdout = Path.of(System.getProperty("catalina.base"), "logs/" + fileName).toFile();
473 if (stdout.exists()) {
474 FileLogAccessor fla = new FileLogAccessor();
475 fla.setName(fileName);
476 fla.setFile(stdout);
477 return fla;
478 }
479 return null;
480 }
481
482
483
484
485
486
487
488
489
490 private LogDestination getCatalinaLogDestination(Context ctx, Application application) {
491 Object log = ctx.getLogger();
492 if (log != null) {
493 CatalinaLoggerAccessor logAccessor = new CatalinaLoggerAccessor();
494 logAccessor.setTarget(log);
495 logAccessor.setApplication(application);
496 if (logAccessor.getFile().exists()) {
497 return logAccessor;
498 }
499 }
500 return null;
501 }
502
503
504
505
506
507
508
509
510
511
512 private LogDestination getCommonsLogDestination(Context ctx, Application application,
513 String logIndex) {
514 Object contextLogger = ctx.getLogger();
515 CommonsLoggerAccessor commonsAccessor = new CommonsLoggerAccessor();
516 commonsAccessor.setTarget(contextLogger);
517 commonsAccessor.setApplication(application);
518 return commonsAccessor.getDestination(logIndex);
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532 private LogDestination getJdk14LogDestination(ClassLoader cl, Application application,
533 boolean root, String logName, String handlerIndex) {
534
535 try {
536 Jdk14ManagerAccessor manager = new Jdk14ManagerAccessor(cl);
537 manager.setApplication(application);
538 Jdk14LoggerAccessor log = root ? manager.getRootLogger() : manager.getLogger(logName);
539 if (log != null) {
540 return log.getHandler(handlerIndex);
541 }
542 } catch (Exception e) {
543 logger.debug("getJdk14LogDestination failed", e);
544 }
545 return null;
546 }
547
548
549
550
551
552
553
554
555
556
557
558
559 private LogDestination getLog4JLogDestination(ClassLoader cl, Application application,
560 boolean root, String logName, String appenderName) {
561
562 try {
563 Log4JManagerAccessor manager = new Log4JManagerAccessor(cl);
564 manager.setApplication(application);
565 Log4JLoggerAccessor log = root ? manager.getRootLogger() : manager.getLogger(logName);
566 if (log != null) {
567 return log.getAppender(appenderName);
568 }
569 } catch (Exception e) {
570 logger.debug("getLog4JLogDestination failed", e);
571 }
572 return null;
573 }
574
575
576
577
578
579
580
581
582
583
584
585
586 private LogDestination getLog4J2LogDestination(Context ctx, Application application, boolean root,
587 String logName, String appenderName) {
588
589 Log4J2AppenderAccessor result = null;
590 try {
591 Loader loader = ctx.getLoader();
592 ClassLoader classLoader = loader.getClassLoader();
593 Log4J2WebLoggerContextUtilsAccessor webLoggerContextUtilsAccessor =
594 new Log4J2WebLoggerContextUtilsAccessor(classLoader);
595 Log4J2LoggerContextAccessor loggerContextAccessor =
596 webLoggerContextUtilsAccessor.getWebLoggerContext(ctx.getServletContext());
597 List<Object> loggerContexts = getLoggerContexts(classLoader);
598 Object loggerConfig = null;
599 for (Object loggerContext : loggerContexts) {
600 Map<String, Object> loggerConfigs = getLoggerConfigs(loggerContext);
601 loggerConfig = loggerConfigs.get(root ? "" : logName);
602 if (loggerConfig != null) {
603 break;
604 }
605 }
606 if (loggerConfig != null) {
607 Log4J2LoggerConfigAccessor accessor = new Log4J2LoggerConfigAccessor();
608 accessor.setTarget(loggerConfig);
609 accessor.setApplication(application);
610 accessor.setContext(true);
611 accessor.setLoggerContext(loggerContextAccessor);
612 result = accessor.getAppender(appenderName);
613 }
614 } catch (Exception e) {
615 logger.debug("getLog4J2LogDestination failed", e);
616 }
617 logger.debug("getLog4J2LogDestination(): OUT: result={}", result);
618
619 return result;
620 }
621
622
623
624
625
626
627
628
629
630
631
632 private Map<String, Object> getLoggerConfigs(Object loggerContext)
633 throws IllegalAccessException, InvocationTargetException {
634 Method getConfiguration =
635 MethodUtils.getAccessibleMethod(loggerContext.getClass(), "getConfiguration");
636 Object configuration = getConfiguration.invoke(loggerContext);
637 Method getLoggerConfigs =
638 MethodUtils.getAccessibleMethod(configuration.getClass(), "getLoggers");
639 return (Map<String, Object>) getLoggerConfigs.invoke(configuration);
640 }
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657 private List<Object> getLoggerContexts(ClassLoader cl) throws ClassNotFoundException,
658 InstantiationException, IllegalAccessException, InvocationTargetException,
659 IllegalArgumentException, NoSuchMethodException, SecurityException {
660 Class<?> clazz =
661 cl.loadClass("org.apache.logging.log4j.core.selector.ClassLoaderContextSelector");
662 Object classLoaderContextSelector = clazz.getDeclaredConstructor().newInstance();
663 Method getLoggerContexts = MethodUtils.getAccessibleMethod(clazz, "getLoggerContexts");
664 return (List<Object>) getLoggerContexts.invoke(classLoaderContextSelector);
665 }
666
667
668
669
670
671
672
673
674
675
676
677
678 private LogDestination getLogbackLogDestination(ClassLoader cl, Application application,
679 boolean root, String logName, String appenderName) {
680
681 try {
682 LogbackFactoryAccessor manager = new LogbackFactoryAccessor(cl);
683 manager.setApplication(application);
684 LogbackLoggerAccessor log = root ? manager.getRootLogger() : manager.getLogger(logName);
685 if (log != null) {
686 return log.getAppender(appenderName);
687 }
688 } catch (Exception e) {
689 logger.debug("getLogbackLogDestination failed", e);
690 }
691 return null;
692 }
693
694
695
696
697
698
699
700
701
702
703
704
705 private LogDestination getLogback13LogDestination(ClassLoader cl, Application application,
706 boolean root, String logName, String appenderName) {
707
708 try {
709 Logback13FactoryAccessor manager = new Logback13FactoryAccessor(cl);
710 manager.setApplication(application);
711 Logback13LoggerAccessor log = root ? manager.getRootLogger() : manager.getLogger(logName);
712 if (log != null) {
713 return log.getAppender(appenderName);
714 }
715 } catch (Exception e) {
716 logger.debug("getLogback13LogDestination failed", e);
717 }
718 return null;
719 }
720
721
722
723
724
725
726
727
728
729
730
731
732 private LogDestination getLogbackTomcatJuliLogDestination(ClassLoader cl, Application application,
733 boolean root, String logName, String appenderName) {
734
735 try {
736 TomcatSlf4jLogbackFactoryAccessor manager = new TomcatSlf4jLogbackFactoryAccessor(cl);
737 manager.setApplication(application);
738 TomcatSlf4jLogbackLoggerAccessor log =
739 root ? manager.getRootLogger() : manager.getLogger(logName);
740 if (log != null) {
741 return log.getAppender(appenderName);
742 }
743 } catch (Exception e) {
744 logger.debug("getTomcatSlf4jLogbackLogDestination failed", e);
745 }
746 return null;
747 }
748
749
750
751
752
753
754
755
756
757
758
759
760 private LogDestination getLogback13TomcatJuliLogDestination(ClassLoader cl,
761 Application application, boolean root, String logName, String appenderName) {
762
763 try {
764 TomcatSlf4jLogback13FactoryAccessor manager = new TomcatSlf4jLogback13FactoryAccessor(cl);
765 manager.setApplication(application);
766 TomcatSlf4jLogback13LoggerAccessor log =
767 root ? manager.getRootLogger() : manager.getLogger(logName);
768 if (log != null) {
769 return log.getAppender(appenderName);
770 }
771 } catch (Exception e) {
772 logger.debug("getTomcatSlf4jLogback13LogDestination failed", e);
773 }
774 return null;
775 }
776
777
778
779
780 private abstract static class AbstractLogComparator
781 implements Comparator<LogDestination>, Serializable {
782
783
784 private static final long serialVersionUID = 1L;
785
786
787 protected static final char DELIM = '!';
788
789 @Override
790 public final int compare(LogDestination o1, LogDestination o2) {
791 String name1 = convertToString(o1);
792 String name2 = convertToString(o2);
793 return name1.compareTo(name2);
794 }
795
796
797
798
799
800
801
802
803 protected abstract String convertToString(LogDestination d1);
804
805 }
806
807
808
809
810 private static class LogDestinationComparator extends AbstractLogComparator
811 implements Serializable {
812
813
814 private static final long serialVersionUID = 1L;
815
816
817 private final boolean all;
818
819
820
821
822
823
824 public LogDestinationComparator(boolean all) {
825 this.all = all;
826 }
827
828 @Override
829 protected String convertToString(LogDestination dest) {
830 File file = dest.getFile();
831 String fileName = file == null ? "" : file.getAbsolutePath();
832 String name;
833 if (all) {
834 Application app = dest.getApplication();
835 String appName = app == null ? Character.toString(DELIM) : app.getName();
836 String context = dest.isContext() ? "is" : "not";
837 String root = dest.isRoot() ? "is" : "not";
838 String logType = dest.getLogType();
839 name = appName + DELIM + context + DELIM + root + DELIM + logType + DELIM + fileName;
840 } else {
841 name = fileName;
842 }
843 return name;
844 }
845
846 }
847
848
849
850
851 private static class LogSourceComparator extends AbstractLogComparator implements Serializable {
852
853
854 private static final long serialVersionUID = 1L;
855
856 @Override
857 protected String convertToString(LogDestination dest) {
858 File file = dest.getFile();
859 String fileName = file == null ? "" : file.getAbsolutePath();
860 Application app = dest.getApplication();
861 String appName = app == null ? Character.toString(DELIM) : app.getName();
862 String logType = dest.getLogType();
863 String context = dest.isContext() ? "is" : "not";
864 String root = dest.isRoot() ? "is" : "not";
865 String logName = dest.getName();
866 return appName + DELIM + logType + DELIM + context + DELIM + root + DELIM + logName + DELIM
867 + fileName;
868 }
869
870 }
871
872 }