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