001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.context.logging; 018 019import java.net.URLClassLoader; 020import java.util.Arrays; 021 022import org.apache.commons.logging.Log; 023import org.apache.commons.logging.LogFactory; 024 025import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; 026import org.springframework.boot.context.event.ApplicationFailedEvent; 027import org.springframework.context.ApplicationEvent; 028import org.springframework.context.event.GenericApplicationListener; 029import org.springframework.context.event.SmartApplicationListener; 030import org.springframework.core.ResolvableType; 031 032/** 033 * A {@link SmartApplicationListener} that reacts to 034 * {@link ApplicationEnvironmentPreparedEvent environment prepared events} and to 035 * {@link ApplicationFailedEvent failed events} by logging the classpath of the thread 036 * context class loader (TCCL) at {@code DEBUG} level. 037 * 038 * @author Andy Wilkinson 039 * @since 2.0.0 040 */ 041public final class ClasspathLoggingApplicationListener 042 implements GenericApplicationListener { 043 044 private static final int ORDER = LoggingApplicationListener.DEFAULT_ORDER + 1; 045 046 private static final Log logger = LogFactory 047 .getLog(ClasspathLoggingApplicationListener.class); 048 049 @Override 050 public void onApplicationEvent(ApplicationEvent event) { 051 if (logger.isDebugEnabled()) { 052 if (event instanceof ApplicationEnvironmentPreparedEvent) { 053 logger.debug("Application started with classpath: " + getClasspath()); 054 } 055 else if (event instanceof ApplicationFailedEvent) { 056 logger.debug( 057 "Application failed to start with classpath: " + getClasspath()); 058 } 059 } 060 } 061 062 @Override 063 public int getOrder() { 064 return ORDER; 065 } 066 067 @Override 068 public boolean supportsEventType(ResolvableType resolvableType) { 069 Class<?> type = resolvableType.getRawClass(); 070 if (type == null) { 071 return false; 072 } 073 return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(type) 074 || ApplicationFailedEvent.class.isAssignableFrom(type); 075 } 076 077 private String getClasspath() { 078 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 079 if (classLoader instanceof URLClassLoader) { 080 return Arrays.toString(((URLClassLoader) classLoader).getURLs()); 081 } 082 return "unknown"; 083 } 084 085}